IEEE 754浮点算术舍入错误在c#和javascript
IEEE 754 floating point arithmetic rounding error in c# and javascript
我刚刚读了一本关于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中二进制浮点数的文章。
对于处理像您的示例(基数为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.1—> 0.10000000000000001 = d (3fb99999 9999999a)
- 0.2—> 0.20000000000000001 = d (3fc99999 9999999a)
- 0.3—> 0.2999999999999999999 = d (3fd33333 33333333)
下一个大于0.2999999999999999999的可表示数是:
- 0.30000000000000004 = d (3fd33333 33333334)
- 0.10000000000000001 + 0.20000000000000001 = 0.30000000000000004
所以你比较的是0.29999999999999999和0.30000000000000004。这是否让你对正在发生的事情有了更深入的了解?
就使用十进制代替二进制表示而言,这也不起作用。以三分之一为例:
- 1/3 = 0.33333333333333333333333333333…
,即使使用十进制数字也没有精确的表示。任何计算都应该考虑到表示错误
既然你已经知道了这个问题,那么解决方法就是在计算浮点数时记住它。
你的例子不完全是你会在一个真正的程序中使用的东西。但是如果真的需要的话,有一些方法可以评估这些东西,一个例子(在c#中)可以是…
if((0.1f + 0.2f).ToString("0.0") == "0.3")
这将是正确的,可能还有许多其他方法。关键是,如果你遇到这种情况,记住潜在的问题。正是这种经验造就了一个更好的开发人员/程序员
- object响应时出现对象错误javascript
- 未捕获的语法错误:javascript对象上出现意外的标记ILLEGAL
- Phonegap-Android 4.4-html5音频长度错误(javascript和媒体插件)
- 未捕获的语法错误:javascript中出现意外的标记}
- 如何从 MVC4 链接调用 Javascript 方法(错误 JavaScript 运行时错误:对象不支持此操作)
- 未捕获类型错误javascript方法
- 将字符串返回到类型为“0”的输出字段;数字“;针对用户错误javascript
- 解析器错误(Javascript初学者寻找解决方案)
- IE 错误 .JavaScript 运行时错误:对象不支持属性或方法“preventDefault”
- appendChild 不是函数错误 (JAVASCRIPT)
- 错误 JavaScript 函数
- 而循环抛出错误JavaScript
- 意外的类型错误 - Javascript,多维数组
- 语法错误:Javascript 中的意外令牌/将数据发布到 Amazon s3
- 语法错误:Javascript 中缺少指数
- 错误“JavaScript 运行时错误:查找滚动位置时无法获取未定义或空引用的属性'scrollLeft'”
- 错误 JavaScript 循环数组
- 错误:Javascript 上的 [对象对象]
- IndexedDBShim.js错误:JavaScript运行时错误:在严格模式下不允许分配只读属性
- 在Evernote listNotebooks API上获取错误-Javascript/Node.Js