ビットコンピューティングのコツはとても面白いです〜

6つの基本的なビット演算子があります:AND、OR、XOR、否定、左シフト、右シフト:

ここに画像の説明を入力してください

ビット演算動作例

ビット演算 特徴
x >> 1 最後の桁を削除します 101101-> 10110
x << 1 最後に0を追加します 101101-> 1011010
x << 1 最後に1を追加します 101101-> 1011011
x | 1 最後の桁を1に変更します 101100-> 101101
x&-2 最後の桁を0に変更します 101101-> 101100
x ^ 1 最後のビットは否定されます 101101-> 101100
x | (1 <<(k-1)) k番目のビットを右から1に回します 101001-> 101101、k = 3
x&〜(1 <<(k-1)) k番目のビットを右から0に回します 101101-> 101001、k = 3
x ^(1 <<(k-1)) 右からk番目が逆になっています 101001-> 101101、k = 3
x&7 最後の3つを取る 1101101-> 101
x&(1 << k-1) 最後のkビットを取る 1101101-> 1101、k = 5
x >>(k-1)&1 右からk番目を取る 1101101-> 1、k = 4
x | ((1 << k)-1) 最後のkビットを1に変換します 101001-> 101111、k = 4
x ^(1 << k-1) 最後のkビットを反転します 101001-> 100110、k = 4
x&(x + 1) 右側の連続する1を0に変えます 100101111-> 100100000
x | (x + 1) 最初の0を右から1に変えます 100101111-> 100111111
x | (x-1) 右側の連続する0を1に変えます 11011000-> 11011111
(x ^(x + 1))>> 1 右側の連続した1を取ります 100101111-> 1111
x&-x 最初の1の左側を右側から削除します 100101000-> 1000
x&0x7F 最後の7つを取る 100101000-> 101000
x&〜0x7F 127未満ですか 001111111&〜0x7F-> 0
x&1 パリティ 00000111&1-> 1

ビット演算を使用する際の2つの考慮事項:

  1. ビット演算は、データの再形成にのみ使用できます。float型とdouble型のビット演算は、コンパイラによって報告されます。
  2. 括弧を使用して演算の順序を確認しようとするため、ビット演算子の演算優先度は比較的低くなります。

1.値が2の整数乗であるかどうかを判別します

問題解決のアイデア:

2の整数乗に対応するバイナリの最上位ビットには1が1つだけあります。たとえば、8、バイナリは1000、4、バイナリは0100、

次に、数値から1を減算し、数値でAND演算を実行します.1を減算すると、2進数が取得されます:7、2進数は0111、3、2進数は0011、8&7は0、

4&3は0です

したがって、nが2の整数乗の場合、n&(n-1)の結果は0でなければなりません。

nの値は0より大きくなければなりません 


1.  public class Main {

3.      public static void main(String[] args) {

4.          int n = 8;

5.          if ((n & (n-1)) == 0){

6.              System.out.println("整数的二次方 true");

7.          }else{

8.              System.out.println("不是整数的二次方");

9.          }

10.      }

11.  }

2.ビット演算を使用して2つの数値を交換します[中間変数を使用しないでください]

XOR


1.  public class Main {

3.      public static void main(String[] args) {

4.          int n = 8, m = 10;

5.          n ^= m;

6.          m ^= n;

7.          n ^= m;

8.          System.out.println(n + ", " + m);

9.      }

10.  }

例:a = 13、b = 6:a
のバイナリは13 = 8 + 4 + 1 = 1101(バイナリ)
bのバイナリは6 = 4 + 2 = 110(バイナリ)

  1. a ^ = ba = 1101 ^ 110 = 1011;
  2. b ^= a b = 110 ^ 1011 = 1101; 即b == 13
  3. a ^= b a = 1011 ^ 1101 = 110; 即a == 6

他の方法、足し算と引き算を使う


1.  public class Main {

3.      public static void main(String[] args) {

4.          int n = 8, m = 10;

5.          n = n + m;

6.          m = n - m;

7.          n = n - m;

8.          System.out.println(n + ", " + m);

9.      }

10.  }

3.32ビット整数のバイナリ表現に含まれる1の数を計算します

x&(x-1)を使用して最後の桁1を削除し、削除された回数を計算します。

といった:

13:1101

12:1100

フェーズおよび:1100、最後の桁を削除


1.  public class Main {

3.      public static void main(String[] args) {

4.          // 计算在一个 32 位的整数的二进制表示中有多少个 1

5.          int m = 13, num = 0;

6.          while (true){

7.              if (m == 0) break;

8.              m &= (m-1);

9.              num ++;

10.          }

11.          System.out.println(num);

12.      }

14.  }

4.正の数は負の数になるか、負の数は正の数になります

変換符号を逆にしてから1を追加するだけです。


1.  public class Main {

3.      public static void main(String[] args) {

4.          // 计算在一个 32 位的整数的二进制表示中有多少个 1

5.          int m = -13;

6.          int changeM = ~m + 1;

7.          System.out.println(changeM);

8.      }

10.  }

5.値のパリティを決定します

最小ビットが0か1かによって決まる限り、0は偶数、1は奇数を意味するので、AND1だけで十分です。

したがって、if(a%2 == 0)の代わりにif((a&1)== 0)を使用して、aが偶数かどうかを判断できます。


1.  public class Main {

3.      public static void main(String[] args) {

4.          int m = -14;

6.          if ((m & 1) == 1){

7.              System.out.println("ji");

8.          }else{

9.              System.out.println("ou");

10.          }

11.      }

13.  }

6.2をm演算の累乗で乗算します

2を掛ける、つまり2を1の累乗し、1ビットを左にシフトする演算

System.out.println(10<<1);

 拡張機能を派生させます。

2をmの累乗で乗算します

System.out.println(10<<2); // 乘以 2的2次方,相当于乘以 4 

7. 2で割る操作(負の奇数の操作は使用できません)

System.out.println(10>>1);

8.絶対値に変換します


1.  public class Main {

3.      public static void main(String[] args) {

4.          int n = 12;

6.          System.out.println(0 >> 31); // 0

7.          System.out.println(10 >> 31);  // 0

8.          System.out.println(-10 >> 31);  // -1

10.          System.out.println((n ^ (n >> 31)) - (n >> 31));  // 12 

12.      }

14.  }
  1. 最初に:n >> 31nの符号を取得します

nが正の数の場合、n >> 31は0に等しくなります。nが負の数の場合、n >> 31は-1に等しくなります。nが正の数の場合、n ^ 0-0は変更されません。

  1. nが負の数n ^ -1の場合、nと-1の補数を計算し、排他的論理和の後に補数を取る必要があります。その結果、nは符号を変更し、絶対値は1で減算されます。マイナス-1は絶対値です

9.2つの数字の符号が同じかどうかを判断します

trueは、xとyの符号が同じであることを意味し、falseは、xとyの符号が反対であることを意味します。

System.out.println((a ^ b) > 0);

10. 2つの整数の平均を求めます(int)

System.out.println((a+b) >> 1);

11.最大2つの整数を見つけます


1.  int max(int a,int b){

2.      return b & ((a-b) >> 31) | a & (~(a-b) >> 31);

3.      /*如果a>=b,(a-b)>>31为0,否则为-1*/

4.  }

12.最小の2つの整数を見つけます


1.  int min(int a,int b){

2.      return a & ((a-b) >> 31) | b & (~(a-b) >> 31);

3.      /*如果a>=b,(a-b)>>31为0,否则为-1*/

4.  }

13.2 つの整数の加算

^ およびを使用 して& 2つの整数を 追加します

  1. 2つの数値のXOR:キャリーを考慮せずに2つの数値を加算することと同じです。
  2. 2つの数値がAND演算され、1つの位置だけ左にシフトされます。キャリーを見つけるのと同じです。

ここに画像の説明を挿入

ここに画像の説明を挿入

13 + 11 = ?;

バイナリの131 1 0 1 ----- a 13

11バイナリ10 1 1 ----- b 11  

 (a&b)<< 1-> 1 0 0 1  0                          ----- d 18

          a ^ b-> 0 1 1  0                    ----- e 6

 (d&e)<< 1-> 0 0 1  0 0                        ------ f 4

          d ^ e-> 1 0 1  0 0                   ----- g 20

 (f&g)<< 1-> 0 1 0 0 0                        ------ h 8

          f ^ g-> 1 0  0 0 0                    ------ i 16

 (h&i)<< 1-> 0  0 0 0 0                       ------ h 0 ---- --------キャリーがないので、ループを終了します

          h ^ i-> 1 1 0 0 0 ------ i 24


1.  private static int getSum(int a, int b) {

2.      if (a == 0) return b;

3.      if (b == 0) return a;

4.      while (b != 0) {

5.          int carry = a & b; // 得到有进位的位置

6.          a = a ^ b; // 直接相加,但是没有进位

7.          b = carry << 1; // 得到进位

8.      }

9.      return a;

10.  }

プロジェクトの推奨事項:

さまざまなコンピューター業界での2000Gを超える電子リソース共有(継続的な更新)

2020WeChatミニプログラムフルスタックプロジェクト-MiaomiaoMaking Friends [コースウェアとソースコード付き]

Spring Bootは、小さくて美しい個人ブログを開発しています[コースウェアとソースコード付き]

Javaマイクロサービスの実際の戦闘大規模ビデオの296エピソード-グレインモール[コードとコースウェア付き]

Java開発マイクロサービスChangbuMallの実際の戦闘[大規模プロジェクトの全357エピソード]-コードとコースウェアを使用

最も完全で詳細なデータ構造とアルゴリズムのビデオ-[コースウェアとソースコード付き]

ここに画像の説明を挿入

おすすめ

転載: blog.51cto.com/14906631/2608802