- 更新:2020-09-17 18:02:17
- 首发:2020-08-07 19:26:16
- 教程
- 4203
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。强大且易于使用。
特征
- 支持数字,大数,复数,分数,单位,字符串,数组和矩阵。
- 与JavaScript的内置Math库兼容。
- 包含一个灵活的表达式解析器。
- 进行符号计算。
- 带有大量内置函数和常量。
- 也可以用作命令行应用程序。
- 在任何JavaScript引擎上运行。
- 很容易扩展。
- 开源。
安装
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()
方法。
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 来判断数字的基数。
- 如果 string 以 "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。
- 如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。
- 如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。
可这带来一个新的问题,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 中可表示的最大的数。
暂无内容
老师你好,我希望能用一个openwrt路由器实现IPv4和IPv6的桥接,请问我该如何实现?我尝试了直接新增dhcpv6的接口,但是效果不甚理想(无法成功获取公网的ipv6,但是直连上级路由的其他设备是可以获取公网的ipv6地)
![%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE20241205230845.png](https://cdn.wyr.me/visitor-files/2024-12-05/1733411344287屏幕截图 2024-12-05 230845.png)你好
,为什么我这里是0039 813C 0600 0075 16xx xx xx,只有前6组是相同的,博客中要前8位相同,这个不同能不能照着修改呢?我系统版本是Win1124H2
大神你好,win11专业版24h2最新版26100.2033,文件如何修改?谢谢
win11专业版24h2最新版26100.2033,Windows Feature Experience Pack 1000.26100.23.0。C:\Windows\System32\termsrv.dll系统自带的这个文件,39 81 3C 06 00 00 0F 85 XX XX XX XX 替换为 B8 00 01 00 00 89 81 38 06 00 00 90。仍然无法远程连接。原来是win11 21h2系统,是可以远程链接的。共享1个主机,2个显示器,2套键鼠,各自独立操作 各自不同的账号,不同的桌面环境。
博主,win11专业版24h2最新版,C:\Windows\System32\termsrv.dll系统自带的这个文件,找不到应该修改哪个字段。我的微信:一三五73二五九五00,谢谢