我很乐意将Integer转换为Float,Float转换为Long,Long转换为Int,然后我对此行为感到困惑。
当我转换表示s
(63 1s)的字符串Long.MAX_VALUE
时,我得到了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);
}
答案 0 :(得分:1)
首先,让我们确认转换是正确的。
Long.MAX_VALUE
是9223372036854775807(19位数)。如您所见,该值大致与您打印的值相同:9.223372E18
。
long
的精确度始终为1
。但是,float
的精确度取决于数字的大小。
在IEEE single-precision floating point number float
中,尾数中只有24位精度,或存储的“分数”部分。因此,float
表示的实际值是Long.MAX_VALUE
的实际值的近似值。
正如您所知,Float.floatToIntBits
方法产生的位数与原始long
位表示不同。
根据IEEE 754浮点“单一格式”位布局返回指定浮点值的表示形式。 位31(由掩码0x80000000选择的位)表示浮点数的符号。位30-23(由掩码0x7f800000选择的位)表示指数。位22-0(由掩码0x007fffff选择的位)表示浮点数的有效位数(有时称为尾数)。
(剪断)
<强>返回强>: 表示浮点数的位。
此方法不会将值转换为int
,它只会提供恰好存储在{{1}中的float
的位表示形式}}。此int
代表的值不应与int
的值相同。
这些零是浮点数的尾数。 float
到long
的实际转换包括找到最高位的符号,找到建立指数的值的大小,并将值的其余部分转换为尾数。
由于float
范围内float
的精度有限,因此会丢失一些精度。最终结果是Long.MAX_VALUE
值略微向上舍入。因为float
是2的幂的1,所以向上舍入产生2的幂,其在尾数中显示为全零。
您可以使用Math.ulp
(最后一个单位)的数字刻度查看浮点值的精度。
Long.MAX_VALUE
产生
Math.ulp(f)
正如您所看到的,1.09951163E12
float
的差异非常大。 (相应的Long.MAX_VALUE
的ulp是double
。大,但比2048.0
的ulp小得多。)但是它与预期的值几乎相差10 < sup> 19 - float
的约7位精度。
答案 1 :(得分:0)
关于print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
:
浮点数的表示方式不同。根据{{3}},有问题的数字在Float的范围内。
中描述了精确转换,包括舍入关于`print(Integer.toBinaryString(intBits)); // 1011111000000000000000000000000怎么来的? s是一串1,现在有0?&#39;:
Float.floatToIntBits(f)
不会返回&#34;与整数&#34;相同的数字。
它的语义在The JavaDoc
答案 2 :(得分:0)
float
表示在四个字节(32位)上,long
表示在8个字节(64位)上。当您将long
转换为float
时,会丢失一半的数据,因为您无法将64位转换为32位。这就是你丢失很多比特的原因。
float
使用23位尾数,因此大于2 ^ 23的整数将被截断。
这就是为什么你能够施放并且施法具有它的结果。