通過原碼 反碼 補碼徹底搞清左移 右移 無符號右移

2021-10-04 19:16:13 字數 4066 閱讀 4744

正數

正數的原碼、反碼、補碼都是該數字的二進位制表示。

首先我們需要知道,計算機中的移位運算都是以二進位制補碼形式進行的,就像我們的integer.tobinarystring(num),其轉化出來的數字就是補碼的形式。在計算機中是沒有正負號的,正數用0表示,負數用1表示。像int,我們知道他是佔32位的,但是他的最大數是2^31 - 1,原因就是他有乙個是符號位。下面先看幾個極限值

system.out.println((1<<31) - 1); //2147483647

system.out.println(1<<31); //-2147483648

int m = -2147483648;

system.out.println(integer.tobinarystring(m)); //10000000000000000000000000000000

由於int型在日常中比較常用,下面就以int型進行講解。

這裡以55進行舉例,為了好理解,我以8位進行講解

int a = 55;

system.out.println(integer.tobinarystring(a)); //110111

55的原碼是00110111,其中符號位是前面的0,其反碼和補碼也是00110111。

負數

負數的原碼是該數字的二進位制表示,反碼是符號位不變數值位取反,補碼是符號位不變數值位在反碼的基礎上加1

我們以-83進行講解,這裡也是用8位進行表示,其實前面還有24位1。

int n = -83;

system.out.println(integer.tobinarystring(n)); //11111111111111111111111110101101

可以看出,輸出的是10101101,這裡是補碼的形式,其中高位的1是符號位。

-83的原碼是 11010011,其中第一位的1是符號位,表示是負數。

-83的反碼是 10101100,其中第一位的1是符號位,表示是負數。

-83的補碼是 10101101,其中第一位的1是符號位,表示是負數。

正數

了解了補碼之後,移位運算就簡單多了,這裡的右移,也是有符號右移,其移位運算就是用的補碼形式。這裡還是用8位的55舉例。

int a = 55;

system.out.println(integer.tobinarystring(a)); //110111

a = a >> 2;

system.out.println(integer.tobinarystring(a)); //1101

system.out.println(a); //13

55的補碼是00110111,右移之後是補碼是00001101,原碼和反碼也是00001101即是13。

負數

負數的有符號右移,這裡還用-83進行講解。

int b = -83;

system.out.println(integer.tobinarystring(b)); //11111111111111111111111110101101

b = b >> 2;

system.out.println(integer.tobinarystring(b)); //11111111111111111111111111101011

system.out.println(b); // -21

-83的原碼是11010011,反碼是10101100,補碼是10101101,所以補碼右移2位後是11101011

11101011轉化為反碼是11101010,轉化為原碼是10010101,即是-21,我們可以看到,移位之後,其位數是不變的,也就是前面的符號位是不變的。

正數

>>>是無符號右移,這裡還是以55講解

int a = 55;

system.out.println(integer.tobinarystring(a)); //110111

a = a >>> 2;

system.out.println(integer.tobinarystring(a)); //1101

system.out.println(a); //13

對於正數而言,有符號右移和無符號右移是一樣的,因為,有符號右移,移動之後是補了符號位0,而無符號右移也是補了0,著重講解負數。

負數

負數還是以-83來進行講解

int b = -83;

system.out.println(integer.tobinarystring(b)); //11111111111111111111111110101101

b = b >>> 2;

system.out.println(integer.tobinarystring(b)); //111111111111111111111111101011

system.out.println(b); // 1073741803

看到這個結果是不是很意外,下面來進行細說一下,你就覺得很合理了。

首先-83的原碼是11010011,反碼是10101100,補碼是10101101,這是我們上面以8位進行表示的,很正常,但是在這裡就不能簡單的用8位來表示了,因為其在無符號右移的時候,前面移出了0,而0取反之後變為了1,所以導致數值變得不敢相信。

這裡進行32位詳細模擬

-83的原碼是 11111111111111111111111111010011

-83的反碼(原碼數值位取反)是 11111111111111111111111110101100

-83的補碼(反碼數值位加1)是 11111111111111111111111110101101

無符號右移2位之後補碼形式是00111111111111111111111111101011,

而其反碼(補碼數值位減1)是01000000000000000000000000010100,

其補碼(反碼數值位取反)是01000000000000000000000000010011

int x = 0b01000000000000000000000000010011;

system.out.println(x); //1073741843

經過檢驗,果然是1073741843

對於左移的話就比較簡單了,因為他不牽扯到符號的問題,符號位不變就行了,由於這個原因,所以就沒有《符號了。

這裡還是以55和-83進行講解

int c = 55;

system.out.println(integer.tobinarystring(c)); //110111

c = c << 2;

system.out.println(integer.tobinarystring(c)); //110111100

system.out.println(c); //220

可以看出,左邊的符號位沒有動,只是在左移2位的時候後面新增了兩個0而已

int d = -83;

system.out.println(integer.tobinarystring(d)); //11111111111111111111111110101101

d = d << 2;

system.out.println(integer.tobinarystring(d)); //11111111111111111111111010110100

system.out.println(d); // -332

也是符號位不變,在左移2位的時候,後面新增了兩個0

有符號:左移1位,相當於乘2,右移動一位相當於除以2

無符號:那真得好好推推了。

原碼 反碼 補碼

正數 原碼 反碼 補碼一樣 7 原 0 0000111 b 7 反 0 0000111 b 7 補 0 0000111 b 負數 原碼就是原來的表示方法 反碼是除符號位 最高位 外取反 補碼 反碼 1 7 原 1 0000111 b 7 反 1 1111000 b 7 補 1 1111001 b 當...

原碼 反碼 補碼

正數 原碼 反碼 補碼一樣 7 原 0 0000111 b 7 反 0 0000111 b 7 補 0 0000111 b 負數 原碼就是原來的表示方法 反碼是除符號位 最高位 外取反 補碼 反碼 1 7 原 1 0000111 b 7 反 1 1111000 b 7 補 1 1111001 b 當...

原碼 反碼 補碼

數值在計算機中表示形式為機器數 計算機只能識別0和1,使用的是二進位制,而在日常生活中人們使用的 是十進位制,正如亞里斯多德早就指出的那樣,今天十進位制的廣泛採用,只不過我們絕大多數人生來具有10個手 指頭這個解剖學事實的結果.儘管在歷史上手指計數 5,10進製 的實踐要比二或三進製計數出現的晚.摘...