我正在尝试下面的代码将字符串转换为float和double但得到不同的结果。
System.out.println(Float.parseFloat("120059389"));
System.out.println(Double.parseDouble("120059389"));
1.20059392E8
1.20059389E8
有人可以解释一下为什么我在float和double中解析字符串会得到不同的结果吗? float和double的范围是什么?
答案 0 :(得分:10)
这是因为你试图通过给它提供比它能处理的精度更多的数字来解析float
。 "ulp" (unit in last place) of a float
那个大8.0
,但"ulp" for a double
那个大的仍然相当小。也就是说,在那个幅度上,最接近的可能float
值相差8
,但最接近double
值的精度更高,相差更远。
System.out.println(Math.ulp(120059389f));
System.out.println(Math.ulp(120059389d));
打印:
8.0
1.4901161193847656E-8
因此Float
解析器必须使用与float
的真实值最接近的120059389
,恰好是1.20059392E8
。
答案 1 :(得分:6)
不同之处在于Double
和Float
以不同方式存储数字。
使用单精度和双精度,允许Double
给予 Double Float
可以处理的精度。
所以简单的答案是,由于Float
与Double
相比有限的内存信息在Float
范围之外的数字转换时会丢失。
Float
:32位数字Double
:64位数字因此,在转换过程中,某些信息在转换为Float
时会丢失,因为它会被截断。
...一般
Float
将数字存储为符号(-/+
)的1位,指数的8位,以及分数的23位。
Double
将数字存储为符号(-/+
)的1位,指数的8位,以及分数的53位。
当你转换你的号码时,120059389 = 111001001111111010111111101b
有27位信息,Double
的53位允许值可以覆盖这些信息,但不能由Float
&#覆盖39; s 23位允许,数据在最不重要的一端被截断。
转换将使用23位1.20059392 = 111001001111111011000000000b
将数字四舍五入到最接近的可表示数字,指数将处理剩余的扩展。
答案 2 :(得分:1)
早期的链接和答案提供了很好的技术答案。 ' laymans'答案是浮点数是32位,双数是64位。其中一些位用于数字,一些用于指数。您在代码中输入的数字只有32位' float'的数字太多。 64位'双'有更多的位,更大的数字可以更精确。
当达到64位双精度且需要128位精度时,相同的概念适用于更大的数字。