C/C++、Java、JavaScript等语言,都有计算不精准的问题。原因是这些语言在计算的时候遵循IEEE 二进制浮点数算术标准(IEEE 754),跟CPU浮点运算器有关系。

“为什么JS中计算0.1加0.2的时候不等于0.3”,“为什么JS中计算4.44乘以100不等于444”,这类问题在诸多程序员岗位的面试中很常见。各个语言也提供了相应的数学库解决计算精度的问题。
在涉及大量计算的JavaScript项目中,强烈推荐使用Math.js这个精确计算库解决JS计算不精准的问题。
Math.js是一个用于JavaScript和Node.js的高级数学计算函数库。它内置大量的函数和常量,具有支持符号计算的表达式解析器,并提供了一个集成的解决方案用于处理不同的数据类型,例如numbers、 big numbers、 complex numbers、 fractions、 units和matrices。强大且易于使用。
npm install mathjs
更多内容请直接访问Math.js的开源仓库:https://github.com/josdejong/mathjs
import { create, all } from 'mathjs'
const config = {
number: 'BigNumber',
precision: 64
}
const math = create(all, config)
math.evaluate('4.44 * 100')
math.evaluate('0.1 + 0.2')

在JavaScript中toFixed()方法可把 Number 四舍五入为指定小数位数的数字。
NumberObject.toFixed(num)
需要注意的是,toFixed()同样存在精度问题。例如2.55取一位小数四舍五入的结果可能是2.5。

在JS自带的函数Math.round()中,3.5将舍入为 4,而 -3.5将舍入为-3。
为了避免这类问题,可以通过mathjs提供的round()方法。
将值四舍五入到最接近的整数。对于矩阵,该函数按元素进行求值。
math.round(x)
math.round(x, n)
| 参数 | 类型 | 描述 |
|---|---|---|
x |
number| BigNumber | Fraction | Complex | Array | Matrix | 四舍五入 |
n |
number| BigNumber | Array | 小数位数默认值:0。 |
| 类型 | 描述 |
|---|---|
| number| BigNumber | Fraction | Complex | Array | Matrix | 取整值 |
math.round(3.2) // returns number 3
math.round(3.8) // returns number 4
math.round(-4.2) // returns number -4
math.round(-4.7) // returns number -5
math.round(math.pi, 3) // returns number 3.142
math.round(123.45678, 2) // returns number 123.46
const c = math.complex(3.2, -2.7)
math.round(c) // returns Complex 3 - 3i
math.round([3.2, 3.8, -4.7]) // returns Array [3, 4, -5]

math.js更多方法:https://mathjs.org/docs/reference/functions.html
在JavaScript中,parseInt()方法可以实现取整。
parseInt(string, radix)
第二个参数radix可选。表示要解析的数字的基数。
同样的,通过parseInt()方法取整也存在精度问题。例如:
parseInt(0.0000001)的结果是1。

解决这个问题,只需要确保传入的第一个参数是字符串即可,例如:parseInt('0.0000001', 10),得到的结果就是0了(**注意:parseInt('1e-7')的结果也是1**)。
第二个参数最好明确指明数字是10进制,否则可能因浏览器遵循的ECMA标准而存在返回值差异。
当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
可这带来一个新的问题,parseInt(0.0000001)产生了隐式转换,得到的结果不是我们想要的。如何将0.0000001正确的转换为'0.0000001'呢?
对于非负小数取整,我们可以采用Math.floor(0.0000001)方法实现向下取整,避免转换过程。
如果是负数,那么Math.floor(-0.0000001)将会得到-1,而parseInt('-0.0000001')得到的结果是-0。
因此,对于不超过4294967295(有效整数,int,范围是0-0xffffffff)的数字来说,JavaScript向下取整,可以采用-0.0000001 | 0,或者-0.0000001 >>> 0来实现。
>>>是无符号位移。所以>>> 0在JS里面是确保数字有意义的判断方法。
1.7976931348623157e+308,这个数字究竟意味着什么?

Number.MAX_SAFE_INTEGER 是js里整数的安全的最大值,由于 js 用的是 IEEE 754 双精度浮点,可以安全地表示 [ -2^53+1 , 2^53-1 ] 这个范围。
Number.MAX_VALUE 属性是 JavaScript 中可表示的最大的数。
C/C++、Java、JavaScript等语言,都有计算不精准的问题。原因是这些语言在计算的时候遵循IEEE 二进制浮点数算术标准(IEEE 754),跟CPU浮点运算器有关系。

“为什么JS中计算0.1加0.2的时候不等于0.3”,“为什么JS中计算4.44乘以100不等于444”,这类问题在诸多程序员岗位的面试中很常见。各个语言也提供了相应的数学库解决计算精度的问题。
在涉及大量计算的JavaScript项目中,强烈推荐使用Math.js这个精确计算库解决JS计算不精准的问题。
Math.js是一个用于JavaScript和Node.js的高级数学计算函数库。它内置大量的函数和常量,具有支持符号计算的表达式解析器,并提供了一个集成的解决方案用于处理不同的数据类型,例如numbers、 big numbers、 complex numbers、 fractions、 units和matrices。强大且易于使用。
npm install mathjs
更多内容请直接访问Math.js的开源仓库:https://github.com/josdejong/mathjs
import { create, all } from 'mathjs'
const config = {
number: 'BigNumber',
precision: 64
}
const math = create(all, config)
math.evaluate('4.44 * 100')
math.evaluate('0.1 + 0.2')

在JavaScript中toFixed()方法可把 Number 四舍五入为指定小数位数的数字。
NumberObject.toFixed(num)
需要注意的是,toFixed()同样存在精度问题。例如2.55取一位小数四舍五入的结果可能是2.5。

在JS自带的函数Math.round()中,3.5将舍入为 4,而 -3.5将舍入为-3。
为了避免这类问题,可以通过mathjs提供的round()方法。
将值四舍五入到最接近的整数。对于矩阵,该函数按元素进行求值。
math.round(x)
math.round(x, n)
| 参数 | 类型 | 描述 |
|---|---|---|
x |
number| BigNumber | Fraction | Complex | Array | Matrix | 四舍五入 |
n |
number| BigNumber | Array | 小数位数默认值:0。 |
| 类型 | 描述 |
|---|---|
| number| BigNumber | Fraction | Complex | Array | Matrix | 取整值 |
math.round(3.2) // returns number 3
math.round(3.8) // returns number 4
math.round(-4.2) // returns number -4
math.round(-4.7) // returns number -5
math.round(math.pi, 3) // returns number 3.142
math.round(123.45678, 2) // returns number 123.46
const c = math.complex(3.2, -2.7)
math.round(c) // returns Complex 3 - 3i
math.round([3.2, 3.8, -4.7]) // returns Array [3, 4, -5]

math.js更多方法:https://mathjs.org/docs/reference/functions.html
在JavaScript中,parseInt()方法可以实现取整。
parseInt(string, radix)
第二个参数radix可选。表示要解析的数字的基数。
同样的,通过parseInt()方法取整也存在精度问题。例如:
parseInt(0.0000001)的结果是1。

解决这个问题,只需要确保传入的第一个参数是字符串即可,例如:parseInt('0.0000001', 10),得到的结果就是0了(**注意:parseInt('1e-7')的结果也是1**)。
第二个参数最好明确指明数字是10进制,否则可能因浏览器遵循的ECMA标准而存在返回值差异。
当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
可这带来一个新的问题,parseInt(0.0000001)产生了隐式转换,得到的结果不是我们想要的。如何将0.0000001正确的转换为'0.0000001'呢?
对于非负小数取整,我们可以采用Math.floor(0.0000001)方法实现向下取整,避免转换过程。
如果是负数,那么Math.floor(-0.0000001)将会得到-1,而parseInt('-0.0000001')得到的结果是-0。
因此,对于不超过4294967295(有效整数,int,范围是0-0xffffffff)的数字来说,JavaScript向下取整,可以采用-0.0000001 | 0,或者-0.0000001 >>> 0来实现。
>>>是无符号位移。所以>>> 0在JS里面是确保数字有意义的判断方法。
1.7976931348623157e+308,这个数字究竟意味着什么?

Number.MAX_SAFE_INTEGER 是js里整数的安全的最大值,由于 js 用的是 IEEE 754 双精度浮点,可以安全地表示 [ -2^53+1 , 2^53-1 ] 这个范围。
Number.MAX_VALUE 属性是 JavaScript 中可表示的最大的数。