[英]Convert Long.MAX_VALUE to Float
通過將Integer轉換為Float,Float轉換為Long,Long轉換為Int,我很開心,然后我對下面的這種行為感到困惑。
當我將一個字符串轉換s
代表Long.MAX_VALUE
(63個1S)我得到了一個NumberFormatException
,其預期。 因為Long
是64位而Integer
是32位所以有額外的31 1。 (這是我的猜測也許是另一個原因請糾正我,如果我錯了)
但是我不確定為什么在將Long
轉換為Float
時沒有得到NumberFormatException
。 再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);
}
首先,讓我們確認轉換是正確的。
Long.MAX_VALUE
是9223372036854775807(19位數)。 如您所見,該值大約是您打印的值: 9.223372E18
。
long
的精度始終為1
。 但是, float
的精度取決於數字的大小。
在一個IEEE單精度浮點數 ,其float
是,有在尾數只有24位精度,或存儲的“分數”的一部分。 因此float
表示的實際值是Long.MAX_VALUE
的實際值的Long.MAX_VALUE
。
正如您Float.floatToIntBits
, Float.floatToIntBits
方法產生的位數與原始long
位表示不同。
根據IEEE 754浮點“單一格式”位布局返回指定浮點值的表示形式。 位31(由掩碼0x80000000選擇的位)表示浮點數的符號。 位30-23(由掩碼0x7f800000選擇的位)表示指數。 比特22-0(由掩碼0x007fffff選擇的比特)表示浮點數的有效數(有時稱為尾數)。
(剪斷)
返回 :表示浮點數的位。
此方法不會將值轉換為int
,它只提供碰巧存儲在int
中的float
的位表示。 此int
表示的值預計不會與float
相同。
那些零是浮點數的尾數。 long
到float
的實際轉換包括找到最高位的符號,找到建立指數的值的大小,並將值的其余部分轉換為尾數。
因為一個的精度float
在規模Long.MAX_VALUE
被限制,一些精度損失。 最終結果是float
值略微向上舍入。 因為Long.MAX_VALUE
是2的冪的1,所以向上舍入產生2的冪,其在尾數中顯示為全零。
您可以使用Math.ulp
(最后一個單位)以數字的比例查看浮點值的精度。
Math.ulp(f)
產量
1.09951163E12
如您所見,對於Long.MAX_VALUE
的float
,差異非常大。 (相應的double
的ulp是2048.0
。大,但是比float
的ulp要小得多。)但是它符合預期值幾乎為10 19 - float
約為7位精度。
關於print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
print(Float.valueOf(s)); //prints 9.223372E18 Why no NumberFormatException? and how did it result 9.223372E18?
:
浮標的表示方式不同。 根據Java語言規范 ,有問題的數字在Float的范圍內。
JavaDoc中描述了精確轉換,包括舍入
關於`print(Integer.toBinaryString(intBits)); // 1011111000000000000000000000000怎么來的? s是1s的字符串現在有0?':
Float.floatToIntBits(f)
不返回“與整數相同的數字”。 它的語義在JavaDoc中描述
float
表示在四個字節(32位)上, long
表示在8個字節(64位)上。 將long
轉換為float
,會丟失一半的數據,因為不能將64位轉換為32位。 這就是你丟失很多比特的原因。
float
使用23位尾數,因此大於2 ^ 23的整數將被截斷。
這就是為什么你能夠施放和施放具有它的結果的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.