[英]Java long assignment confusing
為什么這個Java代碼
long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);
運行時輸出
1
1
107374182400
0
而不是預期的
1
1
107374182400
107374182400
輸出?
long a2 = 100L * 1024 * 1024 * 1024;
但是,在此操作中,至少一個操作數很long
。 因此該運算是使用64位精度執行的,並且數值運算符的結果為long
類型。 另一個非long操作數通過數字提升擴展為long
類型,結果值存儲到變量a2
。
long a1 = 100 * 1024 * 1024 * 1024;
普通整數的常量表達式,表達式的結果計算為int
類型。 但是,計算值太大而無法容納整數,因此會溢出,結果為0
,並存儲到a1
變量中。
編輯:如以下注釋中所述:
為什么不變成負數?
因為在進行整數計算時 ,第二次計算等效於25 * 2^32
,其中^
具有冪的含義,而2^32
整數值為0
。 但是,要解釋為什么其值為0
:在二進制中:
100 * 1024 * 1024 * 1024 == 25 * 2^32;
Integer.MAX_VALUE = 2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000
2 ^ 31
是負整數( -2147483648
),因為符號位為1
,因此2 ^ 32
只是2
到2 ^ 31
的乘積:向左移動,符號位將變為0
,因此結果為0
。
查看java language specification: 4.2.2: Integer operation
以獲取詳細信息。
107374182400恰好是整數(2 ^ 32)整個范圍的25倍 ,這意味着,如果嘗試將其擬合為整數,它將溢出 。 並且因為它恰好適合25次,所以最終精確地為0(這是一個巧合,其他巨大的乘法可能最終為正或負)。 而且您使用的是整數,直到達到長整型為止
long a1 = 100 * 1024 * 1024 * 1024;
相當於
int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;
如果在表達式中放置單個long,則將強制使用long數學而不是整數數學,這可以消除問題
可能是a1
右邊的表達式首先作為int
計算,然后轉換為long
。 如果它的int
等於0
,則它將保持0
long
long a4 = 1L;
//這沒問題
long a3 = 1;
//此處左側的圖元被認為是整數,並且在賦值時將其強制轉換為long值,因此結果再次符合預期
long a2 = 100L * 1024 * 1024 * 1024;
(在這里,您使用了100L,因此其他類型將被強制轉換為Long,因此預期輸出)
long a1 = 100 * 1024 * 1024 * 1024;
(因為默認情況下,Java中任何原始數字都被視為int,它將將此視為整數乘法,因此超出范圍並導致0)
根據Lexical Literals的文檔,其中提到:
文字的類型確定如下:
-以L或l結尾的整數文字(§3.10.1)的類型很長(§4.2.1)。
-任何其他整數文字的類型為int(第4.2.1節)。
因此,您的表達式100 * 1024 * 1024 * 1024
被評估為int
原始數據類型,因為在任何數字值中均未提及l
或L
結果為107374182400
即在Binary中為1 1001 0000 0000 0000 0000 0000 0000 0000 0000
而int
為32位,因此低32位如示例4.2.2-1中所述。 整數運算結果為0
在同一文檔中還提到:
如果除移位運算符外的整數運算符至少具有一個long類型的操作數,則使用64位精度執行該運算,並且數值運算符的結果為long類型。 如果另一個操作數不長,則首先將其加寬(第5.1.5節)以通過數字提升鍵入long
這意味着表達式中的任何值包含l
或L
然后所有int
值都將擴展為64位。
編輯在評論中還要求
為什么不變成負數?
我認為它也回答了上述問題
原因是整數溢出
輸出為100 * 1024 * 1024 * 1024;
是一個不long
的整數( int
)
long a2 = 100L * 1024 * 1024 * 1024;
您指定的值之一是long
(此處為100L
),並且與該值相乘會導致long
值正確存儲在a2
這是您的操作:您將100 * 1024 * 1024 * 1024
分配給長數據類型,但是您沒有說100 * 1024 * 1024 * 1024
是長值
默認情況下,java編譯器認為其為整數。 由於整數不能容納那么多值,因此將顯示錯誤的結果。 希望能幫助到你 !
在Java中,如果您具有int * int,它將把輸出計算為int。 如果您做int * long,則只會給出long的結果。 在您的情況下,100 * 1024 * 1024 * 1024的結果將溢出int。
因此,添加“ L”會使操作數變長,並且計算將值存儲在long中。 當然,不會發生溢出,並且可以輸出正確的結果(即a2)。
數字3起作用是因為您指定了100L的長型。 這就是為什么它是長乘法並且可以存儲的原因。 另一方面,數字4是最大2 ^ 32-1的整數乘法,這就是為什么您溢出並出現零默認值的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.