- 更新:2020-09-17 18:02:17
- 首发:2020-08-07 19:26:16
- 教程
- 3955
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 中可表示的最大的数。
暂无内容
感谢回复! Clang 在生成时沿用了 GCC 的版本号标识,我是不是可以理解为Clang 18.1.4生成时使用的就是GCC4.8,所以我后续使用gcc 9.4
gcov
就会有不兼容的问题抱歉,这块我也不太清楚,尝试寻求AI的帮助吧。
我在这个过程中遇到了各种问题- -,现在在UDC core: g_serial: couldn't find an available UDC卡住了,请问大佬有什么解决方案吗,还是说我前置的设置就错了呢,> 这个需求很特殊。是可以的,但是比较困难,需要修改驱动配置。
好思路呀!!
关于hex编辑器,网上没找到特别好用的(小白没办法),最后在vscode上扩展一搜hex,第一个安装一下就可以用vscode进行hex编译了