2017-11-04 99 views
2

我有两个数字要比较。以下示例中的数字是在两个不同系统中计算的26^26的结果。其中之一是我的JavaScript代码。在Javascript中比较大数字

然而,比较这两个数字,当我结束了这样的事情:

AssertionError [ERR_ASSERTION]: 4.0329146112660565e+26 == 4.0329146112661e+26 

他们显然不是平等的,但理论上他们应该。

什么是正确的方式来执行平等大数字在JavaScript(即使它是一个近似)?

+1

https://github.com/MikeMcl/bignumber。js/ – shotgunner

+0

您可以将数字转换为字符串,然后执行比较 – guest271314

+1

** equal **表示什么意思?严格平等?或等于一些数字?或者等于固定的精度?或可以相互舍入的数字?请指定 –

回答

1

var a = 4.0329146112660565e + 26;

var b = 4.0329146112661e + 26;

一个= Math.round(A/10E + 20)* 10E + 20

B = Math.round(B/10E + 20)* 10E + 20

一个== B;

+0

@Daniel Lord谢谢! '10e + 20'似乎有点神奇。你介意解释它背后的逻辑吗?这个解决方案与@GitaarLAB有关'Number.MAX_SAFE_INTEGER'的建议相结合,对我来说是个诀窍。 'Math.round(4.0329146112661e + 26/Number.MAX_SAFE_INTEGER)* Number.MAX_SAFE_INTEGER;' – Wazeem

+0

@Sam D.似乎你希望精度小于12,因为这是浮点数不同的地方。此解决方案的精度为26 - 20 + 1 = 7。精度为浮点数7逻辑。改变20以获得或失去比较的精度。 –

+0

为什么要将'20'和'26'转换为数字,它已经是一个数字:'10e + 20 == 10e20' – dandavis

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; 
} 

现在我只是想出了确定两个数字之间差异重要性的方法。计算它可能不是一个非常聪明的方法,它可能适用于某些情况而不适用于其他情况。但总的想法是,你必须做出一个函数,用你自己定义的“close”来确定两个值是否足够接近。

但请注意,JavaScript是您可以进行数学运算的最差的语言之一。当整数超出Number.MAX_SAFE_INT(根据Chrome浏览器似乎为9007199254740991,不确定它在浏览器之间或不同浏览器之间或如果这是一个标准化常数)。

+1

标准化常量! IEEE 754 float的自然结果:记住咒语,只存储53个FIRST位(和一个指数)编辑:我们不包括最后可能值(但减去一个)的原因是因为我们希望SAFE int,而我们不能区分2 ** 53 + 1从2 ** 53 – GitaarLAB

+0

这实际上是**相对**精度,而不是**固定**,但是,它肯定可以帮助 –

+1

旁注:没有错误的JavaScript数学(I做很多)。只要了解只有一个数字类型:IEEE 747 64位浮点数。尽管你仍然有我的+1!编辑:只要你想表示的值不需要超过53个有效位,你甚至可以用大于该值的数字进行可靠的数学运算!一旦明白你可以使用本机号码来实现非常有趣的算法(通常是二进制) – GitaarLAB