[英]What's the right way to parseFloat in Java
我注意到Java浮点精度的一些问题
Float.parseFloat("0.0065") - 0.001 // 0.0055000000134110451
new Float("0.027") - 0.001 // 0.02600000000700354575
Float.valueOf("0.074") - 0.001 // 0.07399999999999999999
我不仅有Float
的问题,还有Double
。
有人可以解释幕后发生的事情,我们怎样才能获得准确的数字? 在处理这些问题时,处理此问题的正确方法是什么?
问题在于float
具有有限的精度; 它不能完全代表0.0065
。 (当然, double
也是如此:它具有更高的精度,但仍然是有限的。)
使上述问题更加明显的另一个问题是0.001
是一个double
而不是float
,所以你的float
被提升为double
来执行减法,当然在这一点上系统无法恢复double
可能代表的缺失精度。 为了解决这个问题,你会写:
float f = Float.parseFloat("0.0065") - 0.001f;
使用0.001f
而不是0.001
。
看看每个计算机科学家应该知道的关于浮点运算的内容 。 你的结果对我来说是正确的。
如果您不喜欢浮点数的工作方式,请尝试使用类似BigDecimal的方法 。
你得到了正确的结果。 没有像0.027那样的float
,也没有这样的double
。 如果使用float
或double
则总会出现这些错误。
float
和double
存储为二进制分数 :类似于1/2 + 1/4 + 1/16 ......您无法将所有十进制值精确地存储为有限精度二进制分数。 这在数学上是不可能的。
唯一的选择是使用BigDecimal
,您可以使用它来获取精确的十进制值。
如果浮点字面值以字母
F
或f
结尾,则浮点字面值为float类型; 否则它的类型是双倍的,它可以选择以字母D
或d
结尾。
所以我认为你的文字( 0.001
)是双打的,你从浮动中减去双打。
试试这个:
System.out.println((0.0065F - 0.001D)); // 0.005500000134110451
System.out.println((0.0065F - 0.001F)); // 0.0055
......你会得到:
0.005500000134110451
0.0055
因此,在文字中添加F
后缀,您应该得到更好的结果:
Float.parseFloat("0.0065") - 0.001F
new Float("0.027") - 0.001F
Float.valueOf("0.074") - 0.001F
我会将你的浮点数转换为字符串,然后使用BigDecimal。
这个链接解释得很好
new BigDecimal(String.valueOf(yourDoubleValue));
不要使用BigDecimal双构造函数,因为你仍然会得到错误
如果您需要任意精度,请使用BigDecimal,不要浮动或加倍。 你会看到使用float这种性质的各种舍入问题。
另外要小心不要使用BigDecimal的float / double构造函数,因为它会有同样的问题。 请改用String构造函数。
浮点不能准确表示十进制数。 如果您需要在Java中准确表示数字,则应使用java.math.BigDecimal类:
BigDecimal d = new BigDecimal("0.0065");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.