恍然大悟之原、反、补
曾在很多書籍中看到過關于原碼、反碼和補碼的介紹,都未能夠深入理解。今在Richard Blum編寫的《匯編語言程序設計》一書中讀到關于帶符號整數一節的講解時(確切的說是其中的一句話),的確有茅塞頓開、恍然大悟之感。原文如下:
?
7.2.3 帶符號整數
?
雖然使用無符號整數很容易,但是其缺陷是沒有辦法表示負數。為了解決這個問題,在處理器上需要采用能夠表示負數的方法。有3種方法用于在計算機中描述負數:
(1)帶符號數值(其他書籍中所謂的原碼)
(2)反碼(One's complement)
(3)補碼(Two's complement)
?
所有這3種方法都使用和無符號整數相同的位長度(字節8、字16、雙字32和四字64),但是在位中表示十進制值的方式是不同的。IA-32平臺使用補碼方式表示帶符號整數,但是了解每種方法如何工作是有好處的。下面幾節介紹每種方法。
?
1、帶符號數值
帶符號數值的方法把組成帶符號整數的位分為兩部分:符號位和數值位。字節的最大有效位(最左側的一位)用于表示值的符號。正數的最大有效位包含0,而負數的這個位置是1。值中的其余位使用一般的二進制值表示數字的數值。
帶符號數值的一個問題是有兩種不同的表示0值的方式:00000000(十進制的+0)和10000000(十進制的-0)。這使一些數學處理變得復雜,因為簡單的帶符號整數的加法和減法不能按照無符號數字的方式進行。例如,簡單的加法00000001(十進制1)和10000001(十進制-1)相加得到10000010(十進制-2),這不是正確的答案。這要求處理器為帶符號整數和無符號整數提供不同的數學運算指令。
?
2、反碼
反碼方法采用無符號整數的相反代碼生成相應的負值。求反把所有為0的位改變為1,把所有為1的位改變為0。因此,00000001的反碼就是11111110。同樣,對于帶符號數字,當執行數學操作時,反碼數字會產生一些問題。有兩種方式可以表示零值(00000000和11111111),反碼數字的數學運算也是復雜的(它不允許進行標準二進制運算)。
?
3、補碼
補碼通過使用簡單的數學技巧,解決了帶符號數值和反碼方法的數學運算問題。對于負整數值,值的反碼加上1就是它的補碼。
例如,為了得到十進制-1的補碼,可以這樣做:
1)得到00000001的反碼,結果是11111110.
2)反碼加上1,結果是11111111.
對-2值進行相同的處理,會得到11111110,-3會得到11111101。讀者也許會注意到這里的規律。補碼值從11111111(十進制的-1)開始遞減,直到到達10000000,它表示-128。當然,對于多字節整數長度,相同的規則跨字節使用。
雖然這樣做看上去有些奇怪,但是它解決了帶符號整數的加法和減法的所有問題。例如值00000001(+1)和11111111(-1)相加得到00000000,并且帶有進位值。在整數運算中進位值被忽略,所以最終的值確實是0。相同的硬件可以同時用于無符號值和帶符號值的加法和減法操作。
轉載于:https://www.cnblogs.com/nufangrensheng/p/3897632.html
總結
以上是生活随笔為你收集整理的恍然大悟之原、反、补的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个室内设计师个性签名!
- 下一篇: JS下计算当前日期(当天)后N天出现NA