就是这段代码:
public class Main {
public static void main(String[] args) {
float a = Float.MAX_VALUE;
double b = (double) a;
b++;
System.out.println(b == a);
}
并且它打印true
。
谁能解释一下为什么吗?
最佳答案
double
的精度无法表示Float.MAX_VALUE
和Float.MAX_VALUE+1
之间的差异,因此结果是四舍五入的被返回。舍入结果为 Float.MAX_VALUE
。
Float.MAX_VALUE
为 2128−2104。 (请注意,这是 2127+2126+2125+…+2104。也就是说,它是从 2127 到 2104 的所有 2 的幂之和。在二进制中,它有 24 个 1 位,即有效数的位数1 的 float
。数学上,它等于 2128−2104。)
当你加一时,数学结果当然是 2128−2104+1。这在 double
中无法表示,因为 double
的有效数是 53 位,但从 2127 到 1 是 129 位。您无法将 2127 和 1 的位同时放入 double
的有效数内。当结果不可表示时,返回最接近的可表示数字。
数学结果正下方可表示的数字是 2128−2104,数学结果正上方可表示的数字是 2128>−2104+275。 (请注意,从 2127 到 275 是 52 位,因此 275 是 53 位中的最小 2 的幂有效位数,其中最大位被缩放为 2127。因此,我们通过添加最小的位来计算高于 2128−2104 的下一个数字等于有效数字的数量。)因此我们有两个候选者:
- 2128−2104,与 2128−2104+1 相差 1。
- 2128−2104+275,即 2104+275 −1 距离 2128−2104+1。
前者更接近,所以选择它作为计算结果。因此,在 double
中,2128−2104 加 1 会产生 2128−2104 .
脚注
1 二进制 float 的表示由三部分组成:符号s,即+1或-1,有效数f 是具有固定位数的定点数和指数 e,这样表示的数字为 s • f> • 2e。有效数可以被认为是具有一定位数的整数,但通常通过调整指数来缩放它,以便正常 float 的有效数位于 [1, 2) 中。例如,132 可以被视为有效数 1000012 乘以 22 或 1.000012 乘以 27>.
关于java Float.MAX_VALUE 转 Double,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50839713/