【问题标题】:Is there a way to distinguish integers from very near decimals in Javascript?有没有办法在Javascript中区分整数和非常接近的小数?
【发布时间】:2015-01-08 06:59:43
【问题描述】:

查看那些评估(来自节点 0.10.33 的实际转储)

> parseFloat(2.1e-17) === parseInt(2.1e-17)
false
> parseFloat(2.1e-17 + 2) === parseInt(2.1e-17 + 2)
true
> parseFloat(2.000000000000000000000000000000000009) === parseInt(2.00000000000000000000000000000000000009)
true

如何将整数从非常接近的小数区分为整数?

似乎 JS(或至少 V8)在进行计算时并不关心小于 10^-16 的数字,即使语言 (reference) 使用的 64 位表示应该处理它。

【问题讨论】:

    标签: javascript floating-accuracy floating-point-precision


    【解决方案1】:

    这是我从 ReSharper 学到的东西

    而不是使用类似的表达式

     if (2.00001 == 2) {}
    

    试试

    if (Math.abs(2.00001 - 2) < tolerance) {}
    

    其中容差应该是您可以接受的值,例如 0.001

    所以所有差值小于 .001 的值都等于

    您真的需要 10^-16 精度吗?我的意思是这就是为什么 1000 米 = 1 公里,只需更改输出单位,这样您就不必使用所有这些小数

    【讨论】:

    • 问题是,如果它们小于 10^-16,差异将始终为零,我正在寻找一种方法来更深入地比较两个数字
    • 所以乘以一个大数
    • 它不起作用,正如我在问题中所说,操作实际上会抵消小于 10^-16 的数字
    • 你真的需要 10^-16 精度吗?我的意思是这就是为什么我们有 1000 米和 1 公里,只需更改输出单位,这样你就不必使用所有这些小数
    • 是的,我需要它,无论如何乘以它不会改变任何东西,因为数字以相同的方式表示,如the reference I linked in the question中所述
    【解决方案2】:

    你的例子很容易解释。首先要注意的是,parseInt()parseFloat() 将字符串作为输入。因此,在实际解析之前,您的输入首先会转换为字符串。

    第一个很容易看到:

    > parseFloat(2.1e-17) === parseInt(2.1e-17)
    false
    
    // look at the result of each side
    parseFloat(2.1e-17) == 2.1e-17
    parseInt(2.1e-17)  == 2
    

    当将字符串 "2.1e-17" 解析为整数时,解析将在该点处停止,因为该点不是有效数字,并返回在此之前找到的所有内容,即 2

    > parseFloat(2.1e-17 + 2) === parseInt(2.1e-17 + 2)
    true
    
    // look at the result of each side
    parseFloat(2.1e-17 + 2) == 2
    parseInt(2.1e-17 + 2)  == 2
    

    这里将首先计算参数中的公式。由于浮点数学的限制(我们只有 52 位的尾数,不能表示像 2.000000000000000021 这样的东西),这将导致只有 2。所以parseX()函数都得到相同的整数参数,这将导致相同的解析数字。

    > parseFloat(2.000000000000000000000000000000000009) === parseInt(2.00000000000000000000000000000000000009)
    true
    

    与第二种情况相同的论点。唯一的区别是,这次评估的不是公式,而是 JavaScript 解析器,它将您的数字转换为 2


    总结一下:从 JavaScript 的角度来看,你的数字是一样的。如果您需要更高的精度,则必须使用一些库来获得任意精度。

    【讨论】:

    • 感谢您的回答!我实际上会得出结论 2e-17 + 2 是四舍五入的,因为它的二进制表示 needs more 比 64 位双精度提供的 52 位尾数。如果您在答案中添加此详细信息,我会接受。
    • @mattecapu 2e-16 实际上可以毫无问题地表示。当您尝试评估 (1 + 2e-16) 时,问题就开始了。
    • @mattecapu 好的。为位表示添加了一个句子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2021-01-30
    相关资源
    最近更新 更多