calculate-asmd
Advanced tools
+18
| This software is released under the MIT license: | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| this software and associated documentation files (the "Software"), to deal in | ||
| the Software without restriction, including without limitation the rights to | ||
| use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| the Software, and to permit persons to whom the Software is furnished to do so, | ||
| subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
+120
-41
| "use strict"; | ||
| /** | ||
| 加法 | ||
| **/ | ||
| * [scaleNum 通过操作其字符串将一个浮点数放大或缩小] | ||
| * @param {number} num 要放缩的浮点数 | ||
| * @param {number} pos 小数点移动位数 | ||
| * pos大于0为放大,小于0为缩小;不传则默认将其变成整数 | ||
| * @return {number} 放缩后的数 | ||
| */ | ||
| function scaleNum(num, pos) { | ||
| if (num === 0 || pos === 0) { | ||
| return num; | ||
| } | ||
| let absNum = num; | ||
| let s = 1; | ||
| if (num < 0) { | ||
| absNum = Math.abs(num); | ||
| s = -1; | ||
| } | ||
| let parts = absNum.toString().split("."); | ||
| const intLen = parts[0].length; | ||
| const decimalLen = parts[1] ? parts[1].length : 0; | ||
| // 默认将其变成整数,放大倍数为原来小数位数 | ||
| if (pos === undefined || pos === null) { | ||
| return parseFloat(parts[0] + parts[1]); | ||
| } else if (pos > 0) { | ||
| // 放大 | ||
| let zeros = pos - decimalLen; | ||
| while (zeros > 0) { | ||
| zeros -= 1; | ||
| parts.push(0); | ||
| } | ||
| } else { | ||
| // 缩小 | ||
| let zeros = Math.abs(pos) - intLen; | ||
| while (zeros > 0) { | ||
| zeros -= 1; | ||
| parts.unshift(0); | ||
| } | ||
| } | ||
| const idx = intLen + pos; | ||
| parts = parts.join("").split(""); | ||
| parts.splice(idx > 0 ? idx : 0, 0, "."); | ||
| if (s < 0) { | ||
| parts.unshift("-"); | ||
| } | ||
| return parseFloat(parts.join("")); | ||
| } | ||
| /** | ||
| * [add 通过比较两个加数谁的小数位最大,将两数小数点右移为整数进行计算] | ||
| * @param {number} arg1 加数 | ||
| * @param {number} arg2 被加数 | ||
| * @return {number} 结果 | ||
| */ | ||
| function add(arg1, arg2) { | ||
| var r1 = 0; | ||
| var r2 = 0; | ||
| var m = 0; | ||
| let r1 = 0; | ||
| let r2 = 0; | ||
| let scale = 0; | ||
| try { | ||
@@ -21,4 +77,7 @@ r1 = arg1.toString().split(".")[1].length; | ||
| m = Math.pow(10, Math.max(r1, r2)); | ||
| var result = (arg1 * m + arg2 * m) / m; | ||
| scale = Math.max(r1, r2); | ||
| const num1 = scaleNum(arg1, scale); | ||
| const num2 = scaleNum(arg2, scale); | ||
| const num = num1 + num2; | ||
| const result = scaleNum(num, -scale); | ||
| return result; | ||
@@ -28,8 +87,11 @@ } | ||
| /** | ||
| 减法 | ||
| **/ | ||
| * [sub 通过比较两个加数谁的小数位最大,将两数小数点右移为整数进行计算] | ||
| * @param {number} arg1 减数 | ||
| * @param {number} arg2 被减数 | ||
| * @return {number} 结果 | ||
| */ | ||
| function sub(arg1, arg2) { | ||
| var r1 = 0; | ||
| var r2 = 0; | ||
| var m = 0; | ||
| let r1 = 0; | ||
| let r2 = 0; | ||
| let scale = 0; | ||
| try { | ||
@@ -47,4 +109,7 @@ r1 = arg1.toString().split(".")[1].length; | ||
| m = Math.pow(10, Math.max(r1, r2)); | ||
| var result = (arg1 * m - arg2 * m) / m; | ||
| scale = Math.max(r1, r2); | ||
| const num1 = scaleNum(arg1, scale); | ||
| const num2 = scaleNum(arg2, scale); | ||
| const num = num1 - num2; | ||
| const result = scaleNum(num, -scale); | ||
| return result; | ||
@@ -54,53 +119,67 @@ } | ||
| /** | ||
| 乘法 | ||
| **/ | ||
| * [mul 将两个浮点数参数replace掉小数点为整数计算,scale在这里进行累计小数位] | ||
| * @param {number} arg1 乘数 | ||
| * @param {number} arg2 被乘数 | ||
| * @return {number} 结果 | ||
| */ | ||
| function mul(arg1, arg2) { | ||
| var r1 = Number(arg1.toString().replace(".", "")); | ||
| var r2 = Number(arg2.toString().replace(".", "")); | ||
| var m = 0; | ||
| const num1 = Number(arg1.toString().replace(".", "")); | ||
| const num2 = Number(arg2.toString().replace(".", "")); | ||
| let scale = 0; | ||
| try { | ||
| m += arg1.toString().split(".")[1].length; | ||
| scale += arg1.toString().split(".")[1].length; | ||
| } catch (e) { | ||
| m += 0; | ||
| scale += 0; | ||
| } | ||
| try { | ||
| m += arg2.toString().split(".")[1].length; | ||
| scale += arg2.toString().split(".")[1].length; | ||
| } catch (e) { | ||
| m += 0; | ||
| scale += 0; | ||
| } | ||
| var result = (r1 * r2) / Math.pow(10, m); | ||
| const num = num1 * num2; | ||
| const result = scaleNum(num, -scale); | ||
| return result; | ||
| } | ||
| /** | ||
| 除法 | ||
| **/ | ||
| /** | ||
| * [div 将两个浮点数参数replace掉小数点为整数计算,scale是被除数与除数的移动位数差] | ||
| * @param {number} arg1 除数 | ||
| * @param {number} arg2 被除数 | ||
| * @return {number} 结果 | ||
| */ | ||
| function div(arg1, arg2) { | ||
| var r1 = Number(arg1.toString().replace(".", "")); | ||
| var r2 = Number(arg2.toString().replace(".", "")); | ||
| var l1 = 0; | ||
| var l2 = 0; | ||
| const num1 = Number(arg1.toString().replace(".", "")); | ||
| const num2 = Number(arg2.toString().replace(".", "")); | ||
| let left1 = 0; | ||
| let left2 = 0; | ||
| try { | ||
| l1 = Number(arg1.toString().split(".")[1].length); | ||
| left1 = Number(arg1.toString().split(".")[1].length); | ||
| } catch (e) { | ||
| l1 = 0; | ||
| left1 = 0; | ||
| } | ||
| try { | ||
| l2 = Number(arg2.toString().split(".")[1].length); | ||
| left2 = Number(arg2.toString().split(".")[1].length); | ||
| } catch (e) { | ||
| l2 = 0; | ||
| left2 = 0; | ||
| } | ||
| var pow = Math.pow(10, Math.max(l1, l2)); | ||
| //var result = (Number(r1) / Number(r2)) * Math.pow(10, l2 - l1); 这样也会出现精度问题 | ||
| /** | ||
| * 当被除数100是整数没有移动小数位,那么left2为0,除数0.57在运算中转整数为57。 | ||
| * 在实际的运算中0.57除以100中的0.57是根据被除数来移动小数的。 | ||
| * 所以,0 - 2 = -2。 将运算结果缩小两位为实际小数点位置 | ||
| * | ||
| * 除数多拿了被除数的几口口粮,最后要还回去的。 | ||
| * | ||
| */ | ||
| const scale = left2 - left1; | ||
| const num = num1 / num2; | ||
| //先把结果放大一定倍数,再去移动相应位数 | ||
| var result = r1 / r2; | ||
| result = (result * pow * Math.pow(10, l2 - l1)) / pow; | ||
| const result = scaleNum(num, scale); | ||
| return result; | ||
| } | ||
| module.exports = { add, sub, mul, div }; | ||
| module.exports = { add, sub, mul, div, scaleNum }; |
+1
-1
| { | ||
| "name": "calculate-asmd", | ||
| "version": "2.0.0", | ||
| "version": "3.0.0", | ||
| "description": "加减乘除四则运算(calculate/arithmetic)", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
+34
-18
@@ -7,5 +7,3 @@ # calculate-asmd | ||
| 1. 浮点数值的最高进度是 17 位小数,但在进行运算的时候其精确度却远远不如整数;整数在进行运算的时候都会转成 10 进制。 | ||
| 2. Java 和 JavaScript 中计算小数运算时,都会先将十进制的小数换算到对应的二进制,一部分小数并不能完整的换算为二进制,这里就出现了第一次的误差。 | ||
| 3. 待小数都换算为二进制后,再进行二进制间的运算,得到二进制结果。然后再将二进制结果换算为十进制,这里通常会出现第二次的误差。 | ||
| [浮点数运算 0.2 + 0.4 = 0.6 ?](https://github.com/sanshuiwang/Blog/issues/9) | ||
@@ -28,24 +26,42 @@ > 使用 | ||
| /** 加法 */ | ||
| const addNum = add(9.9, 0.2); | ||
| console.log("add: ", addNum); | ||
| const addNum = add(0.2, 0.4); | ||
| console.log("add(0.2, 0.4): ", addNum); | ||
| const addNegative = add(0.2, -0.4); | ||
| console.log("add(0.2, -0.4): ", addNegative); | ||
| /** | ||
| *add(0.2, 0.4): 0.6 | ||
| *add(0.2, -0.4): -0.2 | ||
| */ | ||
| /** 减法 */ | ||
| const subNum = sub(9.9, 0.2); | ||
| console.log("sub: ", subNum); | ||
| const subNum = sub(0.2, 0.4); | ||
| console.log("sub(0.2, 0.4): ", subNum); | ||
| const subNegative = sub(0.2, -0.4); | ||
| console.log("sub(0.2, -0.4): ", subNegative); | ||
| /** | ||
| *sub(0.2, 0.4): -0.2 | ||
| *sub(0.2, -0.4): 0.6 | ||
| */ | ||
| /** 乘法 */ | ||
| const mulNum = mul(9.9, 0.2); | ||
| console.log("mul: ", mulNum); | ||
| const mulNum = mul(0.57, 100); | ||
| console.log("mul(0.57, 100): ", mulNum); | ||
| const mulNegativ = mul(-0.57, 100); | ||
| console.log("mul(-0.57, 100): ", mulNegativ); | ||
| /** | ||
| *mul(0.57, 100): 57 | ||
| *mul(-0.57, 100): -57 | ||
| */ | ||
| /** 除法 */ | ||
| const divNum = div(9.9, 0.2); | ||
| console.log("div: ", divNum); | ||
| const divNum = div(0.57, 100); | ||
| console.log("div(0.57, 100): ", divNum); | ||
| const divNegative = div(-0.57, 100); | ||
| console.log("div(-0.57, 100): ", divNegative); | ||
| /** | ||
| *div(0.57, 100): 0.0057 | ||
| *div(-0.57, 100): -0.0057 | ||
| */ | ||
| ``` | ||
| > 参考 | ||
| [精确四则运算](https://blog.csdn.net/u010004317/article/details/79009172) | ||
| [js 小数运算出现多位小数如何解决 | ||
| ](http://www.cnblogs.com/zdz8207/p/js-number-tofixed.html) |
+26
-9
@@ -1,12 +0,29 @@ | ||
| const { add, sub, mul, div } = require("../index.js"); | ||
| const { add, sub, mul, div, scaleNum } = require("../index.js"); | ||
| try { | ||
| const addNum = add(9.9, 0.2); | ||
| console.log("add: ", addNum); | ||
| const subNum = sub(9.9, 0.2); | ||
| console.log("sub: ", subNum); | ||
| const addNum = add(0.2, 0.4); | ||
| console.log("add(0.2, 0.4): ", addNum); | ||
| const addNegative = add(0.2, -0.4); | ||
| console.log("add(0.2, -0.4): ", addNegative); | ||
| const mulNum = mul(9.9, 0.2); | ||
| console.log("mul: ", mulNum); | ||
| const divNum = div(9.9, 0.2); | ||
| console.log("div: ", divNum); | ||
| const subNum = sub(0.2, 0.4); | ||
| console.log("sub(0.2, 0.4): ", subNum); | ||
| const subNegative = sub(0.2, -0.4); | ||
| console.log("sub(0.2, -0.4): ", subNegative); | ||
| const mulNum = mul(0.57, 100); | ||
| console.log("mul(0.57, 100): ", mulNum); | ||
| const mulNegativ = mul(-0.57, 100); | ||
| console.log("mul(-0.57, 100): ", mulNegativ); | ||
| const divNum = div(0.57, 100); | ||
| console.log("div(0.57, 100): ", divNum); | ||
| const divNegative = div(-0.57, 100); | ||
| console.log("div(-0.57, 100): ", divNegative); | ||
| console.log(""); | ||
| console.log("scaleNum(0.57,2):", scaleNum(0.57, 2)); | ||
| console.log("scaleNum(-0.57,-2):", scaleNum(-0.57, -2)); | ||
| console.log("scaleNum(0.57,-2):", scaleNum(0.57, -2)); | ||
| console.log("scaleNum(-0.57,2):", scaleNum(-0.57, 2)); | ||
| } catch (error) { | ||
@@ -13,0 +30,0 @@ console.error("error: ", error); |
8426
101.97%5
25%187
81.55%66
32%