我有两个我要比较的数字。以下示例中的数字是在两个不同系统中计算的26^26
的结果。其中一个是我的javascript代码。
然而,当比较这两个数字时,我最终会得到这样的结果:
AssertionError [ERR_ASSERTION]: 4.0329146112660565e+26 == 4.0329146112661e+26
他们显然不相等,但理论上他们应该这样。
在javascript中对大数字执行相等的正确方法是什么(即使它是近似值)?
答案 0 :(得分:3)
如果您要做的是确定两个数字是否实际等效,那么您必须提出误差幅度。一种方法是计算数字之间的差异,然后确定这种差异是否显着。
因此,从之前的数字中,我们可以通过减法来评估这些数字之间的差异。既然我们并不真正关心这种差异的迹象,我会继续前进并获得差异的绝对值。
Math.abs(4.0329146112660565e+26 - 4.0329146112661e+26) === 4329327034368
(旁注:现在不是解释原因的时候,但JavaScript中的==运算符会产生令人困惑且容易出错的行为,当你想要比较值时使用===。)
这个差异是一个巨大的数字,但与我们的数字在多大程度上相关,它是相当微不足道的。直觉上,我很想将差异除以原始数字中最小的一个,如下所示:
4329327034368 / 4.0329146112660565e+26 === 1.0734983136696987e-14
这看起来很小。使用一堆值重复相同的操作,您应该能够确定您想要的误差范围。然后,您所要做的就是使用任意数字执行相同的操作,并查看该差异比率"对你来说足够小。
function similar(a, b) {
let diff = Math.abs(a - b);
let smallest = Math.min(Math.abs(a), Math.abs(b));
let ratio = diff / smallest;
return ratio < MARGIN_OF_ERROR;
}
现在我想出了确定两个数字之间差异的重要性的方法。它可能不是一种非常聪明的计算方法,它可能适用于某些情况而不适用于其他情况。但一般的想法是,你必须制作一个函数来确定两个值是否足够接近你自己的定义&#34; close&#34;。
请注意,JavaScript是您可以进行数学运算的最差语言之一。当它们超出Number.MAX_SAFE_INT(根据Chrome浏览器似乎是9007199254740991,并不确定浏览器之间是否有所不同,或者如果它们不同,整数变得不精确)那是一个标准化的常数。
答案 1 :(得分:1)
var a = 4.0329146112660565e + 26;
var b = 4.0329146112661e + 26;
a = Math.round(a / 10e + 20)* 10e + 20
b = Math.round(b / 10e + 20)* 10e + 20
a == b;
答案 2 :(得分:1)
更新:如果您的目标引擎为es2020
或更高版本,则可以使用新的BigInt
javascript原语来获取大于Number.MAX_SAFE_INTEGER
BigInt(4.0329146112660565e+26) === BigInt(4.0329146112661e+26)
//false
答案 3 :(得分:0)
我建议使用大数字库之一:
示例:
var x = new Big('4.0329146112660565e+26');
var y = new Big('4.0329146112661e+26');
// Should print false
console.log('Comparision result' + x.eq(y));
示例:
var x = bn.of('4.0329146112660565e+26');
var y = bn.of('4.0329146112661e+26');
// Should print false
console.log('Comparision result' + x.equals(y));