如何在Java中避免浮点数或双精度浮点精度错误?
在Java中,我有一个非常恼人的问题,就是浮点数或双倍数的长和。基本上,我的想法是,如果我执行:
for ( float value = 0.0f; value < 1.0f; value += 0.1f )
System.out.println( value );
我得到的是:
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001
我知道浮动精度误差是有积累的,但如何消除呢?我试着用双倍法将误差减半,但结果还是一样
有什么想法吗
# 1 楼答案
另一种解决方案是放弃
==
,并检查这两个值是否足够接近。(我知道这不是你在正文中问的问题,但我在回答问题的标题。)# 2 楼答案
为了完整起见,我推荐这个:
Shewchuck,“鲁棒自适应浮点几何谓词”,如果您想了解更多关于如何使用浮点执行精确算法的示例,或者至少是作者的初衷——http://www.cs.berkeley.edu/~jrs/papers/robustr.pdf
# 3 楼答案
可以使用^{} 之类的类来避免这个特定问题
float
和double
是IEEE 754浮点型,它们的设计目的并不是为了达到完美的精度,而是为了快速。但请注意乔恩下面的观点:BigDecimal
不能准确地表示“三分之一”,正如double
不能准确地表示“十分之一”。但是对于(比如)金融计算,BigDecimal
和类似的类往往是一种方式,因为它们可以用我们人类对数字的思考方式来表示数字# 4 楼答案
这不是一个累积的错误(与Java完全无关)
1.0f
一旦转换为实际代码,就没有0.1的值-您已经得到一个舍入错误从The Floating-Point Guide:
有关详细信息,请阅读链接到网站的链接
# 5 楼答案
不要在迭代器中使用float/double,因为这会使舍入误差最大化。如果你只是使用下面的
它会打印
我知道BigDecimal是一个流行的选择,但我更喜欢double,不是因为它速度快得多,而是它通常要短得多/更容易理解
如果将符号的数量作为代码复杂性的衡量标准
顺便说一句:除非有很好的理由不使用double,否则不要使用float
# 6 楼答案
没有0.1作为
float
或double
的精确表示。由于这种表示错误,结果与您预期的略有不同您可以使用以下几种方法:
double
类型时,只显示所需的数字。当检查是否相等时,允许以较小的公差进行选择李>BigDecimal
可以准确表示0.1李>BigDecimal
的示例代码:在线查看:ideone