int與Long需要注意的值範圍
阿新 • • 發佈:2018-11-09
今天使用程式計算一個算式,算出的結果一點不對,當時就氣死我了。
然後用計算器算了好幾遍,先證明自己邏輯沒有混亂。
這個算式什麼樣子?
System.out.println( "不加L,丟失精度:"+(-1387053568*31 + 19287));
執行結果:明顯不對。
不加L,丟失精度:-48968361
這個計算肯定超過了int的最大值,所以使用Long算一下,
System.out.println( "加上L,正確結果:"+(-1387053568L*31 + 19287));
結果正確:
加上L,正確結果:-42998641321
接著思考這個是怎麼丟失精度的:
先列出int最大,最小值:
System.out.println("測試Integer的值:");
System.out.println( "最大:"+Integer.MAX_VALUE);
System.out.println( "最小:"+Integer.MIN_VALUE);
結果:
測試Integer的值:
最大:2147483647
最小:-2147483648
猜想是不是利用最小的值進行計算的:
System.out.println( "猜想是不是溢位後變成最小值計算,模擬:"+(Integer.MIN_VALUE*31 + 19287));
結果不是用最小值進行計算的,因為與上面的結果不一致:
猜想是不是溢位後變成最小值計算,模擬:-2147464361
看一下這個轉換,這樣就看出丟失精度的過程了:乘法的時候數值超過int最小值範圍,先轉換為一個數,用這個數加的19287
int i =-1387053568*31;
System.out.println("輸出int溢位值:"+i);
溢位結果:
輸出int溢位值:-48987648
這個int超過值範圍是怎麼計算的:這就涉及導java的溢位機制,
涉及到,先轉為二進位制,然後擷取32位(int型別4個位元組,1個位元組八位),然後正負數的補碼,反碼等操作,再轉回十進位制。
有空再繼續寫一下把。//TODO
最後所有程式:
System.out.println("測試Integer的值:");
System.out.println( "最大:"+Integer.MAX_VALUE);
System.out.println( "最小:"+Integer.MIN_VALUE);
int i =-1387053568*31;
System.out.println("輸出int溢位值:"+i);
System.out.println( "加上L,正確結果:"+(-1387053568L*31 + 19287));
System.out.println( "不加L,丟失精度:"+(-1387053568*31 + 19287));
System.out.println( "猜想是不是溢位後變成最小值計算,模擬:"+(Integer.MIN_VALUE*31 + 19287));
System.out.println((int)(-1387053568L*31+ 19287));
//十進位制轉換為二進位制
//二進位制擷取低位32位 原碼 補碼 反碼之類,這裡沒寫完,有興趣可以瞭解一下
String a=Long.toBinaryString((int)(-1387053568L*31));
System.out.println(a);
String sub =a.substring(a.length()-32,a.length());
System.out.println(sub);
System.out.println(sub.length());
System.out.println(Long.valueOf(sub,2).toString());
結果:
測試Integer的值:
最大:2147483647
最小:-2147483648
輸出int溢位值:-48987648
加上L,正確結果:-42998641321
不加L,丟失精度:-48968361
猜想是不是溢位後變成最小值計算,模擬:-2147464361
-48968361
1111111111111111111111111111111111111101000101001000001000000000
11111101000101001000001000000000
32
4245979648