原碼反碼補碼及簡單應用


0 前提

在Java中,所有數據的表示方式都是以補碼形式來表示

在Java中,所有數據的表示方式都是以補碼形式來表示

在Java中,所有數據的表示方式都是以補碼形式來表示

    public static void main(String[] args) {
        int num = 5;
        System.out.println(num + "的補碼 " + Integer.toBinaryString(num));
        num = -1;
        System.out.println(num + "的補碼 " + Integer.toBinaryString(num));
        num = -3;
        System.out.println(num + "的補碼 " + Integer.toBinaryString(num));
    }
# 5的補碼 101   								#int是32位長度  但是前面都是0 省略了
# -1的補碼 11111111111111111111111111111111
# -3的補碼 11111111111111111111111111111101

0.1 機器數

一個數在計算機中的二進制表示形式, 叫做這個數的機器數。機器數是帶符號的,在計算機用一個數的最高位存放符號, 正數0,負數為1

比如,十進制中的數 +3 ,計算機字長為8位,轉換成二進制就是0000 0011。如果是 -3 ,就是 1111 1101 。那么,這里的 00000011 和 1111 1101 就是機器數。 機器數包含了符號和數值部分。

0.2 真值

因為第一位是符號位,所以機器數的形式值就不能很好的表示真正的數值。

例如上面的有符號數1111 1101(8位),其最高位1代表負,其真正數值是 -3 而不是形式值253(1111 1101按無符號整數轉換成十進制等於253)。所以,為區別起見,將帶符號位的機器數對應的真正數值稱為機器數的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –0111 1111 = –127;這里所說的比如-3二進制代碼為10000011,就是我們計算機里面對-3表示的原碼

1 規定

1.1 原碼

原碼:原碼就是符號位加上真值的絕對值, 即用第一位表示符號, 其余位表示值.

比如如果是8位二進制

[+1]原 = 0000 0001

[-1]原 = 1000 0001

[-3]原 = 1000 0011

比如如果是32位二進制

[+1]原 = 0000 0000 0000 0000 0000 0000 0000 0001

[-3]原 = 1000 0000 0000 0000 0000 0000 0000 0011

1.2 反碼

反碼:正數的反碼與其原碼相同;負數的反碼是對其原碼逐位取反,但符號位除外

8位二進制

[+1] = [ 0000 0001 ]原碼 = [ 0000 0001 ]反碼;

[-1] = [ 1000 0001 ]原碼 = [ 1111 1110 ]反碼;

1.3 補碼

補碼:正數的補碼為其本身,負數的補碼為其反碼再加1

8位二進制

[+1]=[0000 0001]原碼=[0000 0001]反碼=[0000 0001]補碼

[-1] =[1000 0001]原碼=[1111 1110]反碼=[1111 1111]補碼

補碼的補碼為原碼

2 總結

  • 在Java中,所有數據的表示方式都是以補碼形式來表示

  • 正數:原碼、反碼、補碼相同

  • 負數:符號位(最高位)為1,其余各位是對原碼取反是反碼,然后反碼加1是補碼

3 二進制運算

  • 與 (&)按位與運算
  • 或 (|)按位或運算
  • 異或 (^)異或運算
  • 非(~)運算符

3.1 測試1

    public static void main(String[] args) {
        int num = ~5;
        System.out.println(num + "的補碼 " + Integer.toBinaryString(num));
    }
#-6的補碼 11111111111111111111111111111010 

解釋

5非運算為什么是-6?

  • 5對應補碼 0000 0101;

  • 5取非(所有二進制位上取非):1111 1010

  • 求補碼1111 1010的原碼,由補碼的補碼就是原碼知:

    [1111 1010] -> 反碼 [1000 0101] ->補碼 [1000 0110]

    則 補碼1111 1010的原碼為1000 0110。

    原碼為1000 0110對應的真值為最高位1為負數,各級求和-1*(4*1 + 2*1)= -6

注意,取非和取反碼不一樣

  • 取非是所有位上都取反;

  • 取反碼,最高位即符號位不取反,其他位取反

3.2 測試2

位移運算:

  • >> n 右移n位,一個正數的補碼整體右移n位,不足補0,負數最高位補1
  • << m 左移m位,一個數的補碼整體左移m位,不足補0
    public static void main(String[] args) {
        int num = 5 << 2;
        System.out.println(num + "的補碼 " + Integer.toBinaryString(num));
        num = 5 >> 5;
        System.out.println(num + "的補碼 " + Integer.toBinaryString(num));
    }
# 20的補碼 10100
# 0的補碼 0

解釋

左移:

  • 5的補碼 0000 0101;
  • 先左移兩位后:0001 0100;(二進制補碼整體左移兩位,末位空出的補上0)
  • 0001 0100計算后1*(16 + 4)= 20;

右移:

  • 5的補碼 0000 0101;
  • 先右移五位后:0000 0000;
  • 對應0

注意:

  • 負數的位移運算要小心,負數右移最高位補的是1,而不是0了

3.3 應用

3.3.1 快速計算奇數還是偶數

    public static void main(String[] args) {
       int num = -150;
       if((num & 1) == 0){
           System.out.println("偶數");
       }else {
           System.out.println("奇數");
       }
    }

3.3.2 快速計算2^n(2的n次方)

    public static void main(String[] args) {
        System.out.println(1 << 16);
    }

注意:整數默認是int,而int是32位有符號整數,取值范圍-2^31 到(2^31 -1)

所以一個數的左移不要超過范圍了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM