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つの考慮事項:
- ビット演算は、データの再形成にのみ使用できます。float型とdouble型のビット演算は、コンパイラによって報告されます。
- 括弧を使用して演算の順序を確認しようとするため、ビット演算子の演算優先度は比較的低くなります。
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(バイナリ)
- a ^ = ba = 1101 ^ 110 = 1011;
- b ^= a b = 110 ^ 1011 = 1101; 即b == 13
- 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. }
- 最初に:n >> 31nの符号を取得します
nが正の数の場合、n >> 31は0に等しくなります。nが負の数の場合、n >> 31は-1に等しくなります。nが正の数の場合、n ^ 0-0は変更されません。
- 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つの整数を 追加します
- 2つの数値のXOR:キャリーを考慮せずに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エピソード]-コードとコースウェアを使用