[英]Java - Decimal Format Precision lost when returning a Float or Decimal
[英]java - float precision when output in console
float x = 0.98123452f;
System.out.println(x); //it prints out 0.9812345
float x = 0.98123453f;
System.out.println(x); //it prints out 0.98123455
我不知道为什么第二个输出是0.98123455而不是0.9812345。 浮点数的精度不是7个十进制数字吗?
要查看浮点数的确切值,可以使用BigDecimal:
float x = 0.98123452f; System.out.println(new BigDecimal(x));
输出:
0.981234490871429443359375
因此,从技术上讲,该浮动:
float x = 0.981234490871429443359375f; System.out.println(new BigDecimal(x)); //prints 0.981234490871429443359375
具有24位精度(显然是挑剔的)...
忘记上面的内容:BigDecimal只有一个double构造函数,因此进行了强制转换为double,并且上面的逻辑存在缺陷。
底线:并非所有数字都可以表示为浮点数,一个浮点数与下一个浮点数之间的距离取决于数字的大小而变化。
IEEE 754的浮点表示形式
0.98123453
是32位(符号,exp,尾数):
0 01111110 11110110011001000110000
这是:
0.9812345504760742
以双精度,然后转换回浮点十进制表示形式:
0.98123455
分配给单精度(浮点数)的位数为32,而双精度则为64位。 还要注意,经常建议使用BigDecimal
,它将您的数字存储为字符串,而不是IEEE754格式。 当需要对数字进行运算时,它将进行转换,并且虽然精度更高,但速度非常慢。
编辑。 为了阐明为什么打印0.98123455,我们需要观察它是数字0.98123453的最接近的单精度表示形式:
00111111011110110011001000101111 = 0.9812345 (sp) = 0.9812344908714294 (dp)
00111111011110110011001000110000 = 0.98123455 (sp) = 0.9812345504760742 (dp)
00111111011110110011001000110001 = 0.9812346 (sp) = 0.981234610080719 (dp)
sp =单精度,dp =双精度
该清单是针对数字附近的[-1,+ 1]二进制范围的,您可以看到0.98123453
最接近尾数的10000
后缀,而0.98123452
最接近后缀01111
。
浮点数的精度不是7个十进制数字吗?
否。它是23位二进制数字。 因此,可以用23位表示的十进制数字的最小数目为6。这不仅仅是在此处的其他答案中所述的“保证”,它是由log10(2 ^ 23)= 6.92369引起的数学重言式。
Java中浮点数的默认输出格式是仅打印足够的数字,以便转换回浮点类型时会产生原始值。
您的代码中发生的详细信息是:
0.98123452f
转换为float
值0.981234490871429443359375。 float
值是0.981234490871429443359375。 但是,将“ 0.981234”转换为float
将产生0.981234014034271240234375,因此需要“ 5”。 0.98123453f
转换为float
值0.98123455047607421875。 有趣的结果是,如果将float
值分配给double
对象,然后打印该double
值,则即使打印的值完全相同,也通常会比打印float
值显示更多的数字。 因为double
格式比float
格式更好(更精确),所以在为float
打印的值(例如0.9812345)和实际值(0.981234490871429443359375)之间可能会有很多double
值。 因此,需要更多的数字来区分该值。
不, float
只有六位数的十进制精度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.