最近在練一些算法題目的時候恰巧碰到了幾道關於int范圍與溢出相關的問題,於是就整理一下。
1、原碼、補碼
在計算機中數值都是用補碼表示和存儲的(正數補碼與原碼一致,負數補碼是原碼符號位不變,其余位取反,然后+1即反碼+1)。
可以通過將這個數每一位和1做&運算得到具體的二進制表示,代碼如下。代碼部分參考https://blog.csdn.net/youyou362/article/details/72667951
1 /** 2 * 將n的每一位與1做&運算 得到具體的二進制表示 3 * @param n 4 * @return 5 */ 6 public static void converseToBinary(int n) { 7 int value = 1; 8 int[] arr = new int[32]; 9 int i = 31; 10 while (value != 0) { 11 if ((value & n) != 0) { 12 arr[i] = 1; 13 } else { 14 arr[i] = 0; 15 } 16 i--; 17 value = value << 1; //左移右邊補0,當移完32為value為0. 18 } 19 for (int index = 0;index < 32;index++){ 20 System.out.print(arr[index]); 21 if ((index+1)%4 == 0){ 22 System.out.print(" "); 23 } 24 } 25 }
例如-3,程序運行結果為 1111 1111 1111 1111 1111 1111 1111 1101 ,正是-3的補碼。由此得知在計算機中數值都是用補碼表示和存儲的。
2、int的取值范圍
java中int四字節,一個字節8bit所以 int 32bit 即高16位和低16位,共32位,最高位符號位。
在Integer類中,有兩個常量 MIN_VALUE和MAX_VALUE是16進制的數。
1 /** 2 * A constant holding the minimum value an {@code int} can 3 * have, -2<sup>31</sup>. 4 */ 5 @Native public static final int MIN_VALUE = 0x80000000; 6 7 /** 8 * A constant holding the maximum value an {@code int} can 9 * have, 2<sup>31</sup>-1. 10 */ 11 @Native public static final int MAX_VALUE = 0x7fffffff;
轉化成二進制分別是MIN_VALUE = 1000 0000 0000 0000 0000 0000 0000 0000;
MAX_VALUE = 0111 1111 1111 1111 1111 1111 1111 1111;
網上看了好多文檔,關於最大值和最小值為什么是這兩個寫的挺模棱兩可的,一開始我猜想正數最大值的時候是因為一共32位,第一位符號位0,剩下都應該是1才是最大,得到正好是0111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111,即2^31 - 1,但已這種方式推算負數最大值時進行不下去,於是用數學歸納法進行總結:
正數部分:1的補碼為 0000 0000 0000 0000 0000 0000 0000 0001;
2的補碼為0000 0000 ............................................. 0010 ;
3的補碼為 0000 0000 ............................................. 0011;
由此推出正數最大值的補碼為 0111 1111 1111 1111 .......................1111,原碼=補碼,為2^31-1;
負數部分:-1的補碼為 1111 1111 1111 1111 1111 1111 1111 1111
-2的補碼為 1111 1111 1111 1111 1111 1111 1111 1110
-3的補碼為 1111 1111 1111 1111 1111 1111 1111 1101
-4的補碼為 1111 1111 1111 1111 1111 1111 1111 1100
由此推出負數最小值的補碼為 1000 0000 0000 0000 0000 0000 0000 0000 0000,求負數最小值補碼的原碼為-2^31
所以int的范圍為-2^31 ~ 2^31-1
3、int的溢出問題,參考自https://www.jianshu.com/p/ffc97c4d2306
溢出是針對有符號數的。
int最大值為 2^31 - 1 補碼為 0111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 加1為 1000 0000 0000 ................0000有溢出,為-2^31
int最小值 -2^31 補碼為 1000 0000 0000 0000 0000 0000 0000 0000 0000 ,-2^31 - 1為加-1的補碼1111 1111 1111 1111 1111 1111 1111 1111
溢出為 1 0111 1111 1111 1111 11111 1111 1111 1111為 2^31 - 1。
本人只是個小白,以上只是個人拙見,如果有問題還請大家指出,有更好的想法歡迎大家留言,一起進步,謝謝!