1. 程式人生 > >C語言系列(二)有符號數和無符號數詳解

C語言系列(二)有符號數和無符號數詳解

1、你自已決定是否需要有正負:

就像我們必須決定某個量使用整數還是實數,使用多大的範圍數一樣,我們必須自已決定某個量是否需要正負。如果這個量不會有負值,那麼我們可以定它為帶正負的型別。

在計算機中,可以區分正負的型別,稱為有符型別(signed),無正負的型別(只有正值),稱為無符型別。 (unsigned)數值型別分為整型或實型,其中整型又分為無符型別或有符型別,而實型則只有符型別。 字元型別也分為有符和無符型別。 比如有兩個量,年齡和庫存,我們可以定前者為無符的字元型別,後者定為有符的整數型別。

2.使用二制數中的最高位表示正負:

首先得知道最高位是哪一位?1個位元組的型別,如字元型別,最高位是第7位,2個位元組的數,最高位是第15位,4個位元組的數,最高位是第31位。不同長度的數值型別,其最高位也就不同,但總是最左邊的那位(如下示意)。字元型別固定是1個位元組,所以最高位總是第7位。

(紅色為最高位)

單位元組數:

11111111

雙位元組數:

11111111 11111111

四位元組數:

11111111 11111111 11111111 11111111

當我們指定一個數量是無符號型別時,那麼其最高位的1或0,和其它位一樣,用來表示該數的大小。
當我們指定一個數量是有符號型別時,此時,最高數稱為“符號位”。為1時,表示該數為負值,為0時表示為正值。

3.無符號數和有符號數的範圍區別:

無符號數中,所有的位都用於直接表示該值的大小。有符號數中最高位用於表示正負,所以,當為正值時,該數的最大值就會變小。我們舉一個位元組的數值對比:

無符號數: 11111111 值:255

這裡寫圖片描述

有符號數: 01111111 值:127

這裡寫圖片描述

eg:(本屌實在不知道怎麼用md語法來打出數學公式,2的冪次方)

同樣是一個位元組,無符號數的最大值是255,而有符號數的最大值是127。原因是有符號數中的最高位被挪去表示符號了。並且,我們知道,最高位的權值也是最高的(對於1位元組數來說是2的7次方=128),所以僅僅少於一位,最大值一下子減半。

不過,有符號數的長處是它可以表示負數。因此,雖然它的在最大值縮水了,卻在負值的方向出現了伸展。我們仍一個位元組的數值對比:

無符號數: 0 —————– 255

有符號數: -128 ——— 0 ———- 127

同樣是一個位元組,無符號的最小值是 0 ,而有符號數的最小值是-128。

所以二者能表達的不同的數值的個數都一樣是256個。只不過前者表達的是0到255這256個數,後者表達的

是-128到+127這256個數。

一個有符號的資料型別的最小值是如何計算出來的呢?

有符號的資料型別的最大值的計算方法完全和無符號一樣,只不過它少了一個最高位(見第3點)。但在負值
範圍內,數值的計算方法不能直接使用1* 26 + 1* 25 的公式進行轉換。

在計算機中,負數除為最高位為1以外,還採用補碼形式進行表達。所以在計算其值前,需要對補碼進行還原。 這裡,先直觀地看一眼補碼的形式:

在10進制中:1 表示正1,而加上負號:-1 表示和1相對的負值。

那麼,我們會很容易認為在2進制中(1個位元組): 0000 0001 表示正1,則高位為1後:1000 0001應該表示-1。

然而,事實上計算機中的規定有些相反,請看下錶:

二進位制(1位元組) 十進位制值
10000000 -128
10000001 -127
10000010 -126
10000011 -125
10000100 -124
…… ……
11111110 -2
11111111 -1

首先我們看到,從-1到-128,其二進位制的最高位都是1,正如我們前面說的,負數最高位為1,然後我們覺得有點奇怪了,1000 0000 並沒有用來表示 0;而 1000 0001也不是拿來直觀地表示-1,事實上,-1用1111 1111來表示。
怎麼理解這個問題呢?先問一句是-1大還是-128大?
當然是-1大,那麼,1111 1111 -1是什麼呢? 和現實中的計算結果完全一致。1111 1111 -1=1111 1110,而1111 1110 就是-2,就這樣一直減下去,當見到只剩最高位用於表示符號的1意外,其他低位全為0時,就是最小的負值,在一位元組中,最小的負值是1000 0000,也就是-128。
我們以-1位例,來看看不同位元組數的整數中,如何表達-1這個數;

位元組數 二進位制值 十進位制值
單位元組數 11111111 -1
雙位元組數 11111111 11111111 -1
四位元組數 11111111 11111111 11111111 11111111 -1

可能有些人看到這裡,就已經混了,為什麼呢?1111 1111 有時表示255,有時又表示-1?所以我再強調 前面說的第二點,你自己決定一個數是有符號還是無符號的,寫程式時,指定一個量是有符號的,那麼當這個量的二進位制各位上的數都是1時,它表示的數就是-1;相反,如果事先宣告這個量是無符號的, 此時它表示的就是該量允許的最大值,對於一個位元組的數來說,最大值就是255。

我們已經知道計算機中,所有資料最終都是使用二進位制數表達。 也已經學會如何將一個10進位制數如何轉換為二進位制數。 不過,我們仍然沒有學習一個負數如何用二進位制表達。 比如,假設有一 int 型別的數,值為5,那麼,我們知道它在計算機中表示為:

00000000 00000000 00000000 00000101  

5轉換成二制是101,不過int型別的數佔用4位元組(32位),所以前面填了一堆0。 現在想知道,-5在計算機中如何表示? 在計算機中,負數以其正值的補碼形式表達。 什麼叫補碼呢?這得從原碼,反碼說起。

原碼:一個整數,按照絕對值大小轉換成的二進位制數,最高為為符號位,稱為原碼。 紅色為符號位

比如:

00000000 00000000 00000000 00000101  是 5的原碼。                                                  10000000 00000000 00000000 00000101  是-5的原碼 

反碼: 將二進位制除符號位數按位取反,所得的新二進位制數稱為原二進位制數的反碼。 正數的反碼為原碼,負數的反碼是原碼符號位外按位取反。

取反操作指:原為1,得0;原為0,得1。(1變0; 0變1)

正數:正數的反碼與原碼相同。
負數:負數的反碼,符號位為“1”,數值部分按位取反。

比如:將10000000 00000000 00000000 00000101除符號位每一位取反,
得11111111 11111111 11111111 11111010。

這時候我們稱:11111111 11111111 11111111 11111010 是 10000000 00000000 00000000 00000101 的反碼。

反碼是相互的, 所以也可稱:
11111111 11111111 11111111 11111010 和 10000000 00000000 00000000 00000101 互為反碼。

補碼: 反碼加1稱為補碼。 (如果反碼最後一位是1得話就向前加1)
1. 正數:正數的補碼和原碼相同。
2. 負數:按照規則來
也就是說,要得到一個數的補碼,先得到反碼,然後將反碼加上1,所得數稱為補碼。
11111111 11111111 11111111 11111010 是 10000000 00000000 00000000 00000101(-5) 的反碼。
加1得11111111 11111111 11111111 11111011
所以,-5 在計算機中表達為:11111111 11111111 11111111 11111011。轉換為十六

進位制:0xFFFFFFFB。
再舉一例,我們來看整數-1在計算機中如何表示。
假設這也是一個int型別,那麼:

1、先取-1的原碼: 10000000 00000000 00000000 00000001
2、除符號位取反得反碼:11111111 11111111 11111111 11111110
3、加1得補碼: 11111111 11111111 11111111 11111111 可見,-1在計算機裡用二進位制表達就是全1。16進製為:0xFFFFFF。

計算機中帶有符號數用補碼錶示的優點:

1、負數的補碼與對應正數的補碼之間的轉換可以用同一種方法——求補運算完成,可以簡化硬體;
2、可將減法變為加法,省去減法器;
3、無符號數及帶符號數的加法運算可以用同一電路完成。

可得出一種心算求補的方法——從最低位開始至找到的第一個1均不變,符號位不變,這之間的各位“求反”(該方法僅用於做題)

方法 例子1 列子2
1,從右邊開始,找到第一個“1” 10101001 10101100
2,從這個“1”之後開始到最左邊取反(不包括符號位,也就是最高位) 11010111 11010100

注意:(如果反碼最後一位是1得話就向前加1)

更多系列相關文章傳送門: