通过将Integer转换为Float,Float转换为Long,Long转换为Int,我很开心,然后我对下面的这种行为感到困惑.
当我转换一个s
代表Long.MAX_VALUE
(63 1s)的字符串时,我得到了一个NumberFormatException
预期的.因为Long
是64位并且Integer
是32位所以有额外的31 1.(这是我的猜测也许是另一个原因请纠正我,如果我错了)
但是我不知道为什么我NumberFormatException
转换Long
到时没有得到Float
.Long
再次是64位,Float
就像32位一样Integer
.我知道位被解释为不同的Float
(IEEE 754浮点"单格式"位布局)但是所有其他额外的31位发生了什么?我真的迷失在这里......
此外,我如何得到9.223372E18这是1011111000000000000000000000000
位串?那些0来自哪里?
public static void main(String[] args){
String s = String.valueOf(Long.MAX_VALUE);
print(s); //prints 9223372036854775807
print(Long.toBinaryString(Long.MAX_VALUE)); //prints 111111111111111111111111111111111111111111111111111111111111111
//Integer.valueOf(s) this throws NumberFormatException because Long is 64 bits and Integer is 32 so s is too large to be an Integer
print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
float f = Float.valueOf(s);
int intBits = Float.floatToIntBits(f);
print(Integer.toBinaryString(intBits)); //1011111000000000000000000000000 How come? s was a String of 1s now there are 0s?
}
public static <T> void print(T arg){
System.out.println(arg);
}
Run Code Online (Sandbox Code Playgroud)
首先,我们来确认一下转换是否正确。
Long.MAX_VALUE
是 9223372036854775807(19 位数字)。正如您所看到的,该值大约是您打印的值:9.223372E18
。
a 的精度long
始终为1
。然而,a 的精度float
取决于数字的大小。
在IEEE 单精度浮点数中,float
尾数或存储的“小数”部分只有 24 位精度。因此 表示的实际值float
是实际值 off 的近似值Long.MAX_VALUE
。
正如您所发现的,该Float.floatToIntBits
方法产生的位与原始long
位表示不同。
根据 IEEE 754 浮点“单一格式”位布局返回指定浮点值的表示形式。位 31(由掩码 0x80000000 选择的位)表示浮点数的符号。位 30-23(由掩码 0x7f800000 选择的位)表示指数。位 22-0(由掩码 0x007fffff 选择的位)表示浮点数的有效数(有时称为尾数)。
(剪断)
返回: 表示浮点数的位。
此方法不会将其值转换为,它仅给出恰好存储在 中的int
位表示形式。由此表示的值预计不会与的值相同。float
int
int
float
这些零是浮点数的尾数。long
to的实际转换float
涉及查找最高有效位的符号、查找值的大小以建立指数,以及将值的其余部分转换为尾数。
float
由于 a在 的尺度上的精度Long.MAX_VALUE
有限,因此会损失一些精度。最终结果是该float
值稍微向上舍入。由于Long.MAX_VALUE
2 的幂差 1,因此向上舍入会产生 2 的幂,尾数中显示为全零。
Math.ulp
您可以使用(最后一位的单位)来查看数字范围内浮点值的精度。
Math.ulp(f)
Run Code Online (Sandbox Code Playgroud)
这产生
1.09951163E12
Run Code Online (Sandbox Code Playgroud)
float
正如您所看到的,对于for来说差异相当大Long.MAX_VALUE
。(相应的 ulpdouble
为2048.0
. Large,但比此处的 ulp 小得多。)但它与几乎 10 19float
的值的预期一致- 大约 7 位精度。float