1. 程式人生 > >二進制和位運算

二進制和位運算

負數 次方 符號位 移位運算 add 數加 結果 使用 16px

一、十進制

  • · 每個位置可以有10個數字,從0到9
  • · 每個位置都有一個位權,從右到左,第一位為1,然後依次乘以10,即第二位為10,第三位為100,依次類推,如:

123表示的1*(10^2) + 2*(10^1) + 3*(10^0),(10^2表示10的二次方),它表示的是各個位置數字含義之和。每個位置的數字含義與位置有關,從右向左,第一位乘以10的0次方,即1,第二位乘以10的1次方,即10,第三位乘以10的2次方,即100,依次類推。

二、二進制

1. 正整數的二進制表示

  • 每個位置只能是0或1。
  • 位權的概念是類似的,從右到左,第一位為1,然後依次乘以2,即第二位為2,第三位為4,依次類推。
  • 使用符合我們直覺的原碼表示法

看一些數字的例子吧:

二進制

十進制

10

2

11

3

111

7

1010

10

2. 負整數的二進制表示

  1. 十進制的負數表示就是在前面加一個負數符號-,例如-123
  2. 二進制使用最高位表示符號位,用1表示負數,用0表示正數。
  3. 使用補碼表示法,補碼表示就是在原碼表示的基礎上取反然後加1。取反就是將0變為1,1變為0。比如:
  • -1:1的原碼表示是00000001,取反是11111110,然後再加1,就是11111111。
  • -2:2的原碼表示是00000010,取反是11111101,然後再加1,就是11111110
  • -127:127的原碼表示是01111111,取反是10000000,然後再加1,就是10000001。

4. 給定一個負數二進制表示,要想知道它的十進制值,可以采用相同的補碼運算。比如:10010010,首先取反,變為01101101,然後加1,結果為01101110,它的十進制值為110,所以原值就是-110。

3. 負整數為什麽采用補碼呢?

  • · 因為只有這種形式,計算機才能實現正確的加減法。
  • · 計算機其實只能做加法

比如:1-1其實是1+(-1)。如果用原碼表示,計算結果是不對的。

1   -> 00000001

-1 -> 10000001

+ ------------------

-2 -> 10000010 //用符合直覺的原碼表示,1-1的結果是-2。

如果是補碼表示:

1   -> 00000001

-1 -> 111111111

+ ------------------

0  ->  00000000 //結果是正確的。

再比如,5-3:

5   -> 00000101

-3 -> 11111101

+ ------------------

2  ->  00000010 //結果也是正確的。

理解了二進制加減法,我們就能理解為什麽正數的運算結果可能出現負數了。當計算結果超出表示範圍的時候,最高位往往是1,然後就會被看做負數。比如說,127+1:

127   -> 01111111

1       -> 00000001

+ ------------------

-128  ->10000000

計算結果超出了byte的表示範圍,會被看做-128。

規律:

  • · 正數的取反等於正數加1取負,例如11的取反等於-12
  • · 負數的取反等於負數加1取正,例如-12的取反等於11

三、十六進制

二進制寫起來太長,為了簡化寫法,可以將四個二進制位簡化為一個0到15的數,10到15用字符A到F表示,這種表示方法稱為16進制,如下所示:

2進制

10進制

16進制

1010

10

A

1011

11

B

1100

12

C

1101

13

D

1110

14

E

1111

15

F

  • 可以用16進制直接寫常量數字,在數字前面加0x即可。比如10進制的123,用16進制表示是0x7B,即123 = 7*16+11。給整數賦值或者進行運算的時候,都可以直接使用16進制,比如:
    • int a = 0x7B;
  • Java中不支持直接寫二進制常量,比如,想寫二進制形式的11001,Java中不能直接寫,可以在前面補0,補足8位,為00011001,然後用16進制表示,即 0x19。

查看整數的二進制和十六進制表示

在Java中,可以方便的使用Integer和Long的方法查看整數的二進制和十六進制表示,例如:

int a = 25; 

System.out.println(Integer.toBinaryString(a)); //二進制

System.out.println(Integer.toHexString(a));  //十六進制

System.out.println(Long.toBinaryString(a)); //二進制

System.out.println(Long.toHexString(a));  //十六進制

四、位運算

  1. 位運算是將數據看做二進制,進行位級別的操作
  2. Java不能單獨表示一個位,但是可以用byte表示8位,可以用16進制寫二進制常量。比如: 0010表示成16進制是 0x2, 110110表示成16進制是 0x36。
  3. 位運算有移位運算和邏輯運算。

1. 移位運算:

  • 左移:操作符為<<,向左移動,右邊的低位補0,高位的就舍棄掉了,將二進制看做整數,左移1位就相當於乘以2。
  • 無符號右移:操作符為>>>,向右移動,右邊的舍棄掉,左邊補0。
  • 有符號右移:操作符為>>,向右移動,右邊的舍棄掉,左邊補什麽取決於原來最高位是什麽,原來是1就補1,原來是0就補0,將二進制看做整數,右移1位相當於除以2。

例如:

int a = 4; // 100

a = a >> 2; // 001,等於1

a = a << 3 // 1000,變為8

2. 邏輯運算:

  • 按位與 &:兩位都為1才為1
  • 按位或 |:只要有一位為1,就為1
  • 按位取反 ~: 1變為0,0變為1
  • 按位異或 ^ :相異為真,相同為假

具體形式,例如:

int a = ...; 

a = a & 0x1 // 返回0或1,就是a最右邊一位的值。

a = a | 0x1 //不管a原來最右邊一位是什麽,都將設為1

二進制和位運算