1. 程式人生 > >以C程式角度探究計算機裡int 型別的儲存與最大數最小數,為什麼負數補碼儲存

以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-10xffffffff1相加運算

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型別的儲存方式,及範圍大小。