c#和javascript中的IEEE 754浮点运算舍入错误
我刚读了一本关于javascript的书。 作者在IEEE 754标准中提到了浮点算术舍入误差。
例如,添加0.1和0.2会产生0.30000000000000004而不是0.3。
所以(0.1 + 0.2) == 0.3
返回false。
我也在c#中重现了这个错误。
所以这些是我的问题是:
发生这种错误的频率如何? 什么是C#和JavaScript中的最佳实践解决方法? 哪些其他语言有相同的错误?
这不是语言错误。 这在IEEE 754中并不是错误的。这是对二进制浮点数的期望和使用的错误。 一旦你理解了二进制浮点数的真正含义,它就非常合理。
在C#中的最佳实践是使用System.Decimal
(又称decimal
),它是一种十进制浮点类型,无论何时处理的数量自然都是以小数表示 - 通常是货币值。
有关.NET二进制浮点数和十进制浮点数的更多信息,请参阅我的文章。
这个错误不是一个舍入误差,只是有些值不能完全由IEEE 754标准表示。 请参阅Jon Skeet有关.net中二进制浮点数的文章以供进一步阅读。
为了处理像你的例子(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
}
这三个数字在双精度浮点上的最接近的表示是:
下一个大于0.29999999999999999的可表示数字是:
最接近的表示
所以你比较0.29999999999999999和0.30000000000000004。 这是否能让你更深入地了解正在发生的事情?
就使用小数而不是二进制表示而言,这也不起作用。 举例来说,有三分之一:
即使使用十进制数字也没有确切的表示。 任何计算都应考虑到表示错误。
链接地址: http://www.djcxy.com/p/27499.html上一篇: IEEE 754 floating point arithmetic rounding error in c# and javascript