什么是原碼、反碼和補(bǔ)碼
1、機(jī)器數(shù)
前言
一個(gè)數(shù)在計(jì)算機(jī)中的表示形式是二進(jìn)制的話,這個(gè)數(shù)其實(shí)就叫機(jī)器數(shù)。
機(jī)器數(shù)通常是帶有符號(hào)的(指有正數(shù)和負(fù)數(shù)之分),計(jì)算機(jī)用最高位存放符號(hào),這個(gè) bit 一般叫做符號(hào)位。 正數(shù)的符號(hào)位為 0, 負(fù)數(shù)的符號(hào)位為 1。比如,十進(jìn)制中的數(shù) +7 ,計(jì)算機(jī)字長(zhǎng)為8位,轉(zhuǎn)換成二進(jìn)制就是 0 0 0 0 0 1 1 1(一個(gè) byte 有 8bit,有效的取值范圍是 -128 ~ +127)。
如果是 -7 ,就是 1 0 0 0 0 1 1 1 。一個(gè)存儲(chǔ)的二進(jìn)制碼分原碼、反碼、補(bǔ)碼,下面我們就來介紹一下什么是原碼、反碼、補(bǔ)碼
Notes
計(jì)算機(jī)底層使用二進(jìn)制形式的補(bǔ)碼來計(jì)算和存儲(chǔ)數(shù)據(jù)
2、原碼
定義
十進(jìn)制數(shù)據(jù)的二進(jìn)制表現(xiàn)形式就是原碼,原碼最左邊的一個(gè)數(shù)字就是符號(hào)位,0為正,1為負(fù)。
例如:56 -> 0 0 1 1 1 0 0 0
左邊第一位為符號(hào)位,其他位為數(shù)據(jù)位。
一個(gè) byte 有 8bit,最大值是 0 1 1 1 1 1 1 1 (+127),最小值是 1 1 1 1 1 1 1 1 (-128)
在計(jì)算機(jī)中之所以使用二進(jìn)制來表示原碼是因?yàn)檫壿嫼?jiǎn)單,對(duì)于電路來說只有開或者關(guān)兩種狀態(tài),用二進(jìn)制是在方便不過的了。如果使用的進(jìn)制是十進(jìn)制、八進(jìn)制或者十六進(jìn)制的話,電路沒有辦法表示那么多的狀態(tài)
- 正數(shù)計(jì)算
使用原碼對(duì)正數(shù)進(jìn)行計(jì)算不會(huì)有任何問題的
例如:5 + 2
0 0 0 0 0 1 0 1
+ 0 0 1 0
-----------------
0 0 0 0 0 1 1 1
把這個(gè)結(jié)果轉(zhuǎn)成十進(jìn)制剛好就等于 7,完全正確無誤
- 負(fù)數(shù)計(jì)算
但是如果是負(fù)數(shù)的話,那計(jì)算的結(jié)果就會(huì)大相徑庭了
我們拿 -56 這個(gè)數(shù)字來舉例,它的原碼是 1 0 1 1 1 0 0 0 ,減一之后,就會(huì)變成 1 0 1 1 0 1 1 1 ,這個(gè)數(shù)轉(zhuǎn)成十進(jìn)制就是 -55。計(jì)算前是 -56,減一之后正確的結(jié)果應(yīng)該是 -57(1 0 1 1 1 0 0 1)才對(duì),居然還越減越大了
1 0 1 1 1 0 0 0
- 1
-----------------
1 0 1 1 0 1 1 1
為了解決原碼不能用于計(jì)算負(fù)數(shù)的這種問題,這時(shí)候,反碼它出現(xiàn)了,作為負(fù)數(shù)的“計(jì)算的救星”。
計(jì)算規(guī)則是正數(shù)的反碼不變和原碼一致,負(fù)數(shù)的反碼會(huì)在原碼的基礎(chǔ)上,高位的符號(hào)位不變,其他位取反( 1 變成 0 , 0 變?yōu)?1 )。
3、反碼
定義
正數(shù)的反碼是其本身(等于原碼),負(fù)數(shù)的反碼是符號(hào)位保持不變,其余位取反。 反碼的存在是為了正確計(jì)算負(fù)數(shù),因?yàn)樵a不能用于計(jì)算負(fù)數(shù)
十進(jìn)制數(shù)字 | 原碼 | 反碼 |
---|---|---|
+0 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 |
-1 | 1000 0001 | 1111 1110 |
-2 | 1000 0010 | 1111 1101 |
-3 | 1000 0011 | 1111 1100 |
-4 | 1000 0100 | 1111 1011 |
-5 | 1000 0101 | 1111 1010 |
-6 | 1000 0110 | 1111 1001 |
-7 | 1000 0111 | 1111 1000 |
- 負(fù)數(shù)計(jì)算
這時(shí)候,我們?cè)賮硎褂梅创a計(jì)算一下 -56 - 1 的結(jié)果
-56 的原碼是 1 0 1 1 1 0 0 0 ,如果轉(zhuǎn)成反碼(符號(hào)位不變,其他位取反),
那么它的反碼就是 1 1 0 0 0 1 1 1
1 1 0 0 0 1 1 1
- 1
-----------------
1 1 0 0 0 1 1 0
-56 -1 = -57,-57 的原碼是 1 0 1 1 1 0 0 1,轉(zhuǎn)成反碼剛好是 1 1 0 0 0 1 1 0,剛好等于剛才我們算出的值
- 跨零計(jì)算
不過反碼也有它的 “ 軟肋 ”,如果是負(fù)數(shù)跨零進(jìn)行計(jì)算的話,計(jì)算得出的結(jié)果不對(duì)
我們拿 -3 + 5 來舉例
-3 的原碼是 1 0 0 0 0 0 1 1,轉(zhuǎn)成反碼的話就是 1 1 1 1 1 1 0 0
1 1 1 1 1 1 0 0
+ 0 1 0 1
-----------------
0 0 0 0 0 0 0 1
把計(jì)算結(jié)果轉(zhuǎn)成十進(jìn)制就是 1,這結(jié)果顯然不對(duì)。那么我們?cè)撛趺从?jì)算呢,這時(shí)候,作為反碼的補(bǔ)充編碼 —— 補(bǔ)碼就出現(xiàn)了。
4、補(bǔ)碼
定義
正數(shù)的補(bǔ)碼是其本身,負(fù)數(shù)的補(bǔ)碼等于其反碼 +1。因?yàn)榉创a不能解決負(fù)數(shù)跨零(類似于 -6 + 7)的問題,所以補(bǔ)碼出現(xiàn)了。
十進(jìn)制數(shù)字 | 原碼 | 反碼 | 補(bǔ)碼 |
---|---|---|---|
+0 | 0000 0000 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 | 0000 0000 |
-1 | 1000 0001 | 1111 1110 | 1111 1111 |
-2 | 1000 0010 | 1111 1101 | 1111 1110 |
-3 | 1000 0011 | 1111 1100 | 1111 1101 |
-4 | 1000 0100 | 1111 1011 | 1111 1100 |
-5 | 1000 0101 | 1111 1010 | 1111 1011 |
-6 | 1000 0110 | 1111 1001 | 1111 1010 |
-7 | 1000 0111 | 1111 1000 | 1111 1001 |
… | … | … | … |
-127 | 1111 1111 | 1000 0000 | 1000 0001 |
-128 | 無 | 無 | 1000 0000 |
- 跨零計(jì)算
這時(shí)候,我們?cè)賮硎褂梅创a計(jì)算一下 -3 + 5 的結(jié)果
-3 的原碼是 1 0 0 0 0 0 1 1,轉(zhuǎn)成反碼的話就是 1 1 1 1 1 1 0 0,再轉(zhuǎn)成補(bǔ)碼就是 1 1 1 1 1 1 0 1
1 1 1 1 1 1 0 1
+ 0 1 0 1
-----------------
0 0 0 0 0 0 1 0
把這個(gè)數(shù)轉(zhuǎn)成十進(jìn)制剛好等于2,結(jié)果正確
5、總結(jié)
在計(jì)算機(jī)當(dāng)中都是使用補(bǔ)碼來進(jìn)行計(jì)算和存儲(chǔ)的。補(bǔ)碼很好的解決了反碼負(fù)數(shù)不能跨零計(jì)算的弊端,并且補(bǔ)碼還可以記錄一個(gè)特殊的值 -128,這個(gè)數(shù)據(jù)在 1 個(gè)字節(jié)下是沒有原碼和反碼
學(xué)習(xí)了原碼、反碼和補(bǔ)碼的知識(shí)之后,我們就可以了解到,Java 當(dāng)中所有的基本數(shù)據(jù)類型。比如整數(shù)類型的數(shù)據(jù)類型,存儲(chǔ)的數(shù)都是同樣的,區(qū)別是在于什么地方,假設(shè)存儲(chǔ)的值都是 10
基本數(shù)據(jù)類型 | 值 | 字節(jié)數(shù) | 內(nèi)存中實(shí)際存儲(chǔ)的值 |
---|---|---|---|
byte | 10 | 1 | 0000 1010 |
short | 10 | 2 | 0000 0000 0000 1010 |
int | 10 | 4 | 0000 0000 0000 0000 0000 0000 0000 1010 |
long | 10 | 8 | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1010 |
從上表中我們可以得出一個(gè)結(jié)論,為了湊齊字節(jié)數(shù),所占的字節(jié)越大,則前面補(bǔ)的零越多。
類型轉(zhuǎn)換原理文章來源:http://www.zghlxwxcb.cn/news/detail-407724.html
- 隱式類型轉(zhuǎn)換
public class Test {
public static void main(String[] args) {
// 小的數(shù)據(jù)類型往大的數(shù)據(jù)類型進(jìn)行轉(zhuǎn)換底層就是通過左補(bǔ)零完成的
byte a = 10; // 0000 1010
int b = a; // 0000 0000 0000 0000 0000 0000 0000 1010
System.out.println(b);
}
}
- 強(qiáng)制類型轉(zhuǎn)換
public class Test {
public static void main(String[] args) {
int a = 300; // 0000 0000 0000 0000 0000 0001 0010 1100
byte b = (byte) a; // 0010 1100
System.out.println(b); // 打印出44
/*
int a = 200; // 0000 0000 0000 0000 0000 0000 1100 1000
byte b = (byte)a; // 1100 1000
System.out.println(b); // 打印出-56
*/
}
}
補(bǔ)碼的運(yùn)算也適用于邏輯運(yùn)算符文章來源地址http://www.zghlxwxcb.cn/news/detail-407724.html
運(yùn)算符 | 含義 | 運(yùn)算規(guī)則 |
---|---|---|
& | 邏輯與 | 0為false,1為true,當(dāng)都為1時(shí)才為true |
| | 邏輯或 | 0為false,1為true,當(dāng)有至少一個(gè)為1時(shí)為true,如果都沒有則為false |
<< | 左移 | 向左移動(dòng),低位補(bǔ)零 |
>> | 右移 | 向右移動(dòng),高位補(bǔ)零,符號(hào)位按照原來數(shù)字的符號(hào)位不變 |
>>> | 無符號(hào)右移 | 向右移動(dòng),高位補(bǔ)零 |
到了這里,關(guān)于什么是原碼、反碼和補(bǔ)碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!