c#和javascript中的IEEE 754浮点算术舍入错误

c#和javascript中的IEEE 754浮点算术舍入错误,c#,javascript,floating-point,ieee-754,C#,Javascript,Floating Point,Ieee 754,我刚读了一本关于javascript的书。作者在IEEE 754标准中提到了浮点算术舍入误差 例如,添加0.1和0.2将产生0.300000000004,而不是0.3 因此(0.1+0.2)==0.3返回false 我还在c#中重现了这个错误 我的问题是: 这种错误发生的频率有多高? c#和javascript的最佳实践解决方案是什么? 哪些其他语言也有相同的错误?现在您已经知道了这个问题,解决方法是在计算浮点数时记住这一点 您的示例并不完全是您在实际程序中使用的示例。但是如果真的需要的话,有一

我刚读了一本关于javascript的书。作者在IEEE 754标准中提到了浮点算术舍入误差

例如,添加0.1和0.2将产生0.300000000004,而不是0.3

因此
(0.1+0.2)==0.3
返回false

我还在c#中重现了这个错误

我的问题是:

这种错误发生的频率有多高? c#和javascript的最佳实践解决方案是什么?
哪些其他语言也有相同的错误?

现在您已经知道了这个问题,解决方法是在计算浮点数时记住这一点

您的示例并不完全是您在实际程序中使用的示例。但是如果真的需要的话,有一些方法可以评估这些东西,例如(C#)

if((0.1f + 0.2f).ToString("0.0") == "0.3")

这是真的,可能还有很多其他的方法。关键是,如果你曾经遇到过这种情况,那么记住潜在的问题。正是这种经验造就了一个更好的开发人员/程序员。这不是语言中的错误。这不是IEEE 754中的错误。这是一个错误的期望和使用二进制浮点数。一旦您了解了二进制浮点数的真正含义,它就非常有意义了

C#中的最佳实践是使用
System.Decimal
(又称
Decimal
)这是一种十进制浮点类型,无论何时处理自然以十进制表示的量——通常是货币值


有关更多信息,请参阅我在.NET上的文章。

错误不是一个舍入错误,只是一些值不能由IEEE 754标准精确表示。更多阅读请参见Jon Skeet的文章

要处理像示例(base-10)这样的数字,您应该使用C#中的
decimal
数据类型,因为它可以准确地表示这些数字,所以您可以得到预期的值

典型的方法是定义一些
epsilon
值,并检查结果是否在targetvalue+-epsilon范围内:

double const epsilon = 0.000001; // or whatever

if(valueA >= valueB - epsilon && valueA <= valueB + epsilon)
{
    // treat as valueA = valueB
}
double const epsilon=0.000001;//或者别的什么

如果(valueA>=valueB-epsilon&&valueA这三个数字在双精度浮点中的最接近表示为:

  • 0.1-->0.100000000000001=D(3FB9999999999A)
  • 0.2-->0.200000000001=D(3FC9999999999A)
  • 0.3-->0.299999999999=D(3FD33333 33333)
下一个大于0.2999999999999的可表示数字为:

  • 0.300000000000000004=D(3FD33333 3333 4)
最接近的代表

  • 0.100000000000001+0.200000000001等于0.300000000004
所以你比较的是0.29999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

至于使用十进制而不是二进制表示,这也不起作用。以三分之一为例:

  • 1/3=0.3333333333

即使使用十进制数字也没有精确的表示法。任何计算都应该考虑表示错误。

有一本书称之为“舍入错误”??还有:它的链接不是“错误”因为它是经过设计的,但它是一个讨厌的东西。我确信在某些情况下,这将是一个有用的行为,但在实践中(至少在JavaScript中),我认为如果默认的表示形式是一个“正确的”(精确的基数10)十进制,它会更有用。我从来没有想要过二进制浮点数。这本书是Nicholas C.Zakas编写的《面向Web开发人员的JavaScript》第二版。第33页描述了“错误”。