以C程式角度探究計算機裡int 型別的儲存與最大數最小數,為什麼負數補碼儲存
一c語言運算int最大值,最小值
首先我們寫這樣一個程式,讓計算機自己計算能儲存的最大值。
PS:我採用的是GCC編譯器,在CODEBLOCK環境下呼叫gcc編譯的。(我的計算機intel core i5處理器,32位win7作業系統)
給s賦一個初值,取得比較大,因為太小的話,程式執行時間很長。當然這樣有點事後諸葛亮的嫌疑,最好是賦值為1,但是執行時間太長。有興趣可以自己試一下。
程式碼如下
int main() { time_t start,end; start=clock(); int s=2147400000;//為什麼初值取這麼大呢?因為太小,運算時間太長 while(1) { tt: s+=1; printf("值=%d\n",s); if(s<0) {printf("int資料最大值=%d\n",s-1); break; } if(s>0) goto tt; } end=clock(); printf("程式執行時間為:%lf\n秒",difftime(end,start)/CLOCKS_PER_SEC); return 0; }
運算結果如下
由此可以知道最大值是2147483647.
下面我們寫一個類似的程式,來輸出int型別最小負數。
int main() {//計算最小值 time_t start,end; start=clock(); int s=-2147480000;//為什麼初值取這麼大呢?因為太小,運算時間太長 while(1) { tt: s-=1; printf("值=%d\n",s); if(s>0) {printf("int資料最小值=%d\n",s+1); break; } if(s<0) goto tt; } end=clock(); printf("程式執行時間為:%lf\n秒",difftime(end,start)/CLOCKS_PER_SEC); return 0; }
執行結果如下
由此我們知道最小值就是我們在第一個計算最大值的時候,溢位的第一個負數。
二:關於最大值,最小值的進一步測試
1:首先我想知道,我採用的編譯環境下,int型別採用幾個位元組儲存。
sizeof(int)可以告訴我結果,是4個位元組,32位。
2:最大的數,是不是採用0xffff ffff ffff ffff表示的呢?我也想知道,所有測試下。
3:計算機儲存負整數,最高位是符號位,來區分正整數負整數,那麼0x8000 0000 0000 0001是表示-1麼?
這是我想知道的問題,所以寫下列程式測試。
程式碼如下:
#include <iostream> //計算機裡int型別的儲存與資料範圍,溢位問題 using namespace std; int main() { cout<<"int型別佔用位元組"<<sizeof(int)<<endl;//判斷當前編譯環境下int儲存的位元組數,輸出為4,4位元組,32位 int i=0x00000001; //定義一個int型別變數,32位 cout<<i<<endl; i=i<<1; //左移一位,正常,無溢位 cout<<i<<endl; //最大的數是不是0xffffffff呢?輸出看一下就知道 i=0xffffffff; cout<<"0xffffffff表示的數是最大整數麼?i="<<i<<endl; //輸出結果是-1(如果你學習過計算機原理,負數二進位制表示換算成十進位制,全部取反,+1) //最大整數是多少? int j=0x80000001; cout<<"j=0x80000001是-1麼?j="<<j<<endl; i=0x7fffffff; //最大正數範圍,0b0111 1111 1111 1111 cout<<"0x7fffffff表示的數="<<i<<endl; j=i+1; cout<<"0x7fffffff+1表示的數="<<j<<endl; //+1之後溢位,0x80000000 i=0x80000000; //最高位是1,符號位,其餘31位都是0,取反31位都是1,再加上1,0x cout<<"0x80000000表示的數="<<i<<endl; //最小值 i=i-1; cout<<"0x80000000減去1="<<i<<endl; return 0; }
執行結果如下
告訴我們很多資訊。int是4個位元組。0xffff ffff ffff ffff並不是最大正數,0x8000 0000 0000 0001也不是-1。
原來0x7fff ffff 是最大正整數.
0xffff ffff 是-1最大負整數。
0x8000 0000是最小負數。
三:計算機儲存0x80000001為什麼不表示-1?
如果我們採用0x8000 0001表示-1,那麼我們在與正整數相加時候會遇到這樣的問題。
例子:-1+1=0
0000 0000 0000 0000 0000 0000 0000 0001 |
1 |
|
+ |
8000 0000 0000 0000 0000 0000 0000 0001 |
-1 |
= |
8000 0000 0000 0000 0000 0000 0000 0010(-2) |
0 |
這樣的計算與正整數不相同。
正常的正整數相加的運算規則不適用於正整數與負整數的加法,因此必須制定兩套運算規則,一套用於正整數加正整數,還有一套用於正整數加負整數。從電路上說,就是必須為加法運算做兩種電路。
在第二部分,我們用C語言程式,測試知道。0xffff ffff表示的是-1-1是0xffffffff和1相加運算
0000 0000 0000 0000 0000 0000 0000 0001 |
1 |
|
+ |
1111 1111 1111 1111 1111 1111 1111 1111 |
-1 |
= |
0000 0000 0000 0000 0000 0000 0000 0000 (進位是1,捨棄) |
0 |
這樣的運算就正確。在計算機裡,我們就可以採用一種電路來計算,正整數相加,正整數與負整數相加。這樣的話,規則通用,一套加法電路就可以了。
這種在現有計算機體系中採用的負整數的表示方式,稱為補碼錶示法。0xffff ffff 最高位是符號位,其餘位全部取反就是0x80000000 ,這個數再加1,就是0x8000 0001,就是-1.
對於所有的負整數,我們都可以採用這樣的補碼規則得到它實際表示的數。
至此,我們可以清楚了計算機裡int型別的儲存方式,及範圍大小。