INT_MAX INT_MIN及其运算
轉(zhuǎn)自:知乎阿貴
C++中常量INT_MAX和INT_MIN分別表示最大、最小整數(shù),定義在頭文件limits.h中。
#define INT_MAX 2147483647 #define INT_MIN (-INT_MAX - 1)因為int占4字節(jié)32位,根據(jù)二進制編碼的規(guī)則,INT_MAX = 2^31-1,INT_MIN= -2^31.
在C/C++語言中,不能夠直接使用-2147483648來代替最小負數(shù),因為這不是一個數(shù)字,而是一個表達式。表達式的意思是對整數(shù)21473648取負,但是2147483648已經(jīng)溢出了int的上限,所以定義為(-INT_MAX -1)。
上溢是2147483647很容易理解,2147483647=2^31-1 (因為要有一個符號位,所以把第一位作為符號位,0為正,1為負),但為什么下溢的時候分明是31位來表示的數(shù)會出現(xiàn)2147483648呢??
以八位整數(shù)為例
00000000到01111111,表示0到+127。10000001到11111111,表示-1到-127。大家可以注意到,10000000我們沒有用到。因為如果我們把它看成-0,那么會和00000000發(fā)生重復(fù)。于是計算機將10000000定義為-128(即在最終進位后符號位不產(chǎn)生進位)。
(1) 對于無符號n位整數(shù),表示范圍很好理解[0 ~ 2^n?1];
(2) n位有符號整數(shù)的表示范圍為[?2^(n?1) ~ 2^(n?1)?1],對于有符號整數(shù),計算機使用補碼表示,同時在表示時采用了下面的準則:
最高位為符號位,正數(shù)為0,負數(shù)為1;
正數(shù)的反碼以及補碼與原碼相同;
負數(shù)需要對除符號位以外的所有位取反得到反碼,然后反碼加1得到補碼。
首先從原碼講起,原碼即為計算機中對數(shù)值的二進制表示,如 5用二進制表示為0000 0101 ;
其次就是反碼,反碼,顧名思義取反,對于正數(shù)來說,反碼與原碼相同;對于負數(shù)來說,反碼為原碼的各位取反(符號位除外),如
正數(shù)(0011 0111)的反碼為: 0011 0111 ,
負數(shù)(1101 0010)的反碼為: 1010 1101 ;
再次就是補碼,計算機中,數(shù)值疑慮用補碼表示和存儲的,正數(shù)的補碼與原碼相同,負數(shù)的補碼為其反碼+1,如
正數(shù)(0101 1101)補=0101 1101
負數(shù)(1101 0010)補=1010 1110
由于計算中的CPU只有加法器,沒有減法器,所以在計算機采用原碼做減法是會存在這樣的問題:對于1-1=0
看做1+(-1)=0 二進制表示 0001+1001=1001 變成了十進制的負1而不是0。
補碼的出現(xiàn)很好的解決了這個問題,由于采用補碼運算,則
補碼加法成為:[X+Y]補 = [X]補 + [Y]補
補碼的減法變?yōu)?#xff1a;[X-Y]補 = [X]補 - [Y]補 = [X]補 + [-Y]補
補碼的乘法變?yōu)?#xff1a;【X*Y】補=【X】補×【Y】補;
在此我們以減法為例說明補碼的優(yōu)勢,還以上述為題為例:(0001)補+(1001)補 = 0001 + 1111 = 0000 (最高位的進位省略),這樣就順利得到了0
另外,補碼還解決了原碼中存在兩個0 的問題(即+0 和 -0),以8進制為例,int_8的取值范圍應(yīng)該是-127~ -0和+0~ 127 即存在(正0): 0000 0000 和 (負 0):1000 0000 ,但是在兩個0轉(zhuǎn)換為補碼后全部都變成了0000 0000,
但是這樣就會有一個補碼(1000 0000 )沒有用到,對于1000 0000 ,任何原碼都不能轉(zhuǎn)換成補碼后成為1000 0000的形式。所以人為規(guī)定補碼中 1000 0000 表示 -128 ,這就很好的解釋了,為什么8位的整形變量的下溢下界會是-128而上溢上界是127了。
同樣,對于16進制int,也是這樣, 表示范圍成了 - 32768 ~ 32767 (32768=2^16)
關(guān)于INT_MAX INT_MIN的運算
由于二進制編碼按原碼、補碼和反碼的規(guī)則進行運算,所有程序中對INT_MAX和INT_MIN的運算應(yīng)當(dāng)格外注意,在出現(xiàn)溢出的時候,不遵循數(shù)學(xué)規(guī)則。
INT_MAX + 1 = INT_MIN
0111 1111 + 0000 0001 = 補碼 0111 1111 + 補碼0000 0001 = 補碼 1000 0000 = -128
INT_MIN - 1 = INT_MAX
INI_MIN + 1000 0001 = 補碼1000 0000 + 補碼 1111 1111 = 補碼 0111 1111 = 127
abs(INT_MIN) = INT_MIN
比較有趣的是,INT_MAX + 1 < INT_MAX, INT_MIN - 1 > INT_MIN, abs(INT_MIN) < 0.
總結(jié)
以上是生活随笔為你收集整理的INT_MAX INT_MIN及其运算的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 精读5G:关于5G的NSA和SA,看完秒
- 下一篇: 从零实现简易播放器:4.ffmpeg 解