js精度计算

JavaScript09

js精度计算,第1张

在新公司的第一个项目是区块链相关的管理后台和交易所,其中就涉及了很多的计算问题。而JavaScript因为存在计算的精度问题,所以直接计算就可能会导致各种各样的bug,为了解决这个问题,就要使用BigNumber.js这个库。

至于为什么JavaScript会有精度问题呢,可以看 这里 。简单来说就是因为: JavaScript中所有的数字(包括整数和小数)都只有一种类型–Number。它的实现遵循IEEE 754标准,使用64位固定长度来表示,也就是标准的double双精度浮点数。它的优点是可以归一化处理整数和小数,节省储存空间。而实际计算的时候会转换成二进制计算再转成十进制。进制转换之后会很长,舍去一部分,计算再转回来,就有了精度误差。

BigNumber.js是一个用于任意精度计算的js库。可以在  官方文档  的console中测试使用。也可以通过npm install bignumber.js --save来安装。然后 import BigNumber from 'bignumber.js' 来引入使用。他的大概原理是将所有数字当做字符串,重新实现了计算逻辑。缺点是性能比原生的差很多。

现在 TC39 已经有一个 Stage 3 的提案 proposal bigint,大数问题有望彻底解决。在浏览器正式支持前,可以使用 Babel 7.0 来实现,它的内部是自动转换成 big-integer 来计算,要注意的是这样能保持精度但运算效率会降低。

具体用法可以参考以下资料:

官方文档

bignumber.js使用记录

BigNumber 讲解

就不再敖述了,下边随便写点常用的方法:

// 转为 bignumberconstx=newBigNumber('123456789.123456789')// 转为 普通数字x.toNumber()// 格式化(小数点)x.toFormat()// '123,456,789.123456789'x.toFormat(3)// '123,456,789.123'// 计算x.plus(0.1)// 加法x.minus(0.1)// 减法x.times(0.1)// 乘法x.div(0.1)// 除法x.mod(3)// 取模/取余// 比较大小x.eq(y)// isEqualTo 的简写,是否相等x.gt(y)// isGreaterThan 的简写,是否大于x.gte(y)// isGreaterThanOrEqualTo 的简写,是否大于等于x.lt(y)// isLessThan 的简写,是否小于x.lte(y)// isLessThanOrEqualTo 的简写,是否小于等于// 取非,改变数字的正负号x.negated()

可以直接将数字进行计算

function Add(num1,num2){

    return (num1+num2)//返回num1和num2的和

    

    //return (num1-num2)//返回num1和num2的差

    //return (num1*num2)//返回num1和num2相乘结果

    //return (num1/num2)//返回num1和num2相除结果

}

返回由字符串转换得到的整数。

parseInt(numString, [radix])

参数:numString 必选项。要转换为数字的字符串。

radix 可选项。在 2 和 36 之间的表示 numString 所保存数字的进制的值。如果没有提供,则前缀为 '0x' 的字符串被当作十六进制,前缀为 '0' 的字符串被当作八进制。所有其它字符串都被当作是十进制的。

说明 :parseInt 方法返回与保存在 numString 中的数字值相等的整数。如果 numString 的前缀不能解释为整数,则返回 NaN(而不是数字)。

parseInt("abc") // 返回 NaN。

parseInt("12abc") // 返回 12。

可以用 isNaN 方法检测 NaN。

-----------------------------

floor 返回不大于的最大整数

round 则是4舍5入的计算,入的时候是到大于它的整数

ceil 则是不小于他的最小整数

因为运算动作 setTotal 放在了 加减 按钮的 click 事件中

若你想通过改变数量来触发 setTotal 那可以 尝试 定义 input元素的 失去焦点 blur 事件来触发 setTotal