|
とても基礎的な知識ですが、長期間使わないと忘れてしまいますので、コーディングしながらどんどん活用していきましょう!
話は安いので、コードを見せてください。
注: これらを単独で議論すると、アプリケーションを見るのは非常に困難です。他の人のまとめもチェックできます。
コードを使用してビット演算のアプリケーションを見てみましょう:
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
このコードは、DataOutputStream
クラスのメソッドであり、int 型の整数を変換するために使用されます。ストリームに書き込みます。このメソッドのネーミングは非常に興味深いもので、OutputStream
の public abstract void write(int b) throws IOException
とはまったく異なります。このメソッドのパラメータは、ストリームに整数を書き込むことができることを示しているようですが、メソッドの機能は推測されず、メソッドの説明に依存します。
public abstract void write(int b) throws IOException
API の概要:
指定されたバイトをこの出力ストリームに書き込みます。write の一般的な規約は、1 バイトが出力ストリームに書き込まれることです。書き込まれるバイトは、引数 b の下位 8 ビットです。b の上位 24 ビットは無視されます。
it Itストリームに特定のバイトを書き込むことです。int 型変数は 32 ビット、バイトは 8 ビットを占めることがわかっているため、256 (2^8) 未満の int 型整数とバイト型整数の最後の 8 ビットは同一です。
つまり、この方法では、int 変数の下位 8 ビットを書き込み、残りの 24 ビットを無視します。この方法を使用する場合は特に注意してください。
書き込まれるバイトは、引数 b の下位 8 ビットです。b の上位 24 ビットは無視されます。
したがって、int 型変数を完全にストリームに書き込むことは、それほど単純な問題ではありません。上記のコードに戻りますが、1 バイトのデータを 4 回連続して書き込むことで、int 型の変数が 4 バイトに変換されてストリームに書き込まれます。
out.write((v >>> 24) & 0xFF); このメソッドは、上記の下位 8 桁の数字を書き込むことであり、この特定の実装は対応しています。サブクラスごとに。
図を見てみましょう: 単純な AND 演算: 演算の結果は、下位 8 ビット、つまり (v>>>24) & を保持していることがわかります。 0xFF 操作の結果。
では、上位 8 ビット値を取得するにはどうすればよいでしょうか?これにはシフト演算を使用する必要があります。
#シフト演算を実行することで、各 8 ビットのデータを取得し、ビット単位の AND & 演算を実行することで、完全に行うことができます。整数をストリームに書き込みます。
コードのデモ
コード
package dragon;
/**
* 分析这一个方法,目前水平有限,先从最简单的做起!
* */
// public final void writeInt(int v) throws IOException {
// out.write((v >>> 24) & 0xFF);
// out.write((v >>> 16) & 0xFF);
// out.write((v >>> 8) & 0xFF);
// out.write((v >>> 0) & 0xFF);
// incCount(4);
// }
//上面这段代码是将一个32位整型,写入输出流。
//并且是将32位整型分为4个部分,每次写入8位。
//这是Java的特性。
public class DataOutputStreamAnalysis {
public static void main(String[] args) {
DataOutputStreamAnalysis analysis = new DataOutputStreamAnalysis();
analysis.analysis(65535);
}
public void analysis(int number) {
int number1, number2, number3, number4; //后面的数字表示是一个32位整型的第几个8位。
number1 = (number >>> 24) & 0xFF;
number2 = (number >>> 16) & 0xFF;
number3 = (number >>> 8) & 0xFF;
number4 = (number >>> 0) & 0xFF;
System.out.println(this.format(Integer.toBinaryString(number))+" 原始数据");
System.out.println(this.format(Integer.toBinaryString(number1))+" 原始数据第一个8位");
System.out.println(this.format(Integer.toBinaryString(number2))+" 原始数据第二个8位");
System.out.println(this.format(Integer.toBinaryString(number3))+" 原始数据第三个8位");
System.out.println(this.format(Integer.toBinaryString(number4))+" 原始数据第四个8位");
}
/**
* 输入一个二进制字符串,将其格式化,因为整型是
* 占32位的,但是转换成的二进制字符串,并没有32位*/
public String format(String bstr) {
int len = bstr.length();
StringBuilder sb = new StringBuilder(35);
for (int i = 0; i < 32-len; i++) {
sb.append("0");
}
sb.append(bstr);
sb.insert(8, " ");
sb.insert(17, " ");
sb.insert(26, " "); //前面插入一个字符后,所有字符的索引都变了!
return sb.toString();
}
}
結果
説明: 負の数は使用できません。ここで考慮する 状況は同じですが、負の数の表現が少し面倒になります。正の数を理解している限り、負の数は問題ありません。
ビット演算の応用
1. int 型変数 x が奇数か偶数かを判定
ビットごとの AND 演算を実行します。変数 x と 1 の結果が 0 の場合、変数 x は偶数であり、それ以外の場合は奇数です。
if (x & 1 ==0)
System.out.println("x是偶数");
if (x & 1 == 1)
System.out.println("x是奇数");
説明: 偶数の最終シフトは 0 でなければならないため、これでも理解しやすいです。 (バイナリ表現)
2. int 型変数の k 番目のビットを取得します ビットのバイナリ値。
式: x >> k & 1 (わかりやすくするために括弧を追加することをお勧めします。)
3. int 型を変更します。変数のk番目の位置1 式:
x = x | (1 4. int 型変数の k 番目のビットを 0 クリアします。 1をkビット左にシフトし、その結果を反転して変数に加えて論理演算すると、変数xのk番目のビットが0にクリアされ、他のビットは変更されません。 式ビット:
x = x & ~(1 ##5. 2 つの整数の平均を計算します 式ビット:(x & y) ((x ^ y) >> 1)
6. 1 より大きい整数 x について、次のことを判断します。 x は 2
if (x & (x-1) == 0)
System.out.println("x是2的次幂");
7 の累乗です。数値を 2
の n 乗で乗算します。式: x = x
例: x を 2 倍に拡張します: x = x
ビット単位の演算が推奨される理由:
ビット操作は必要な命令が少なく、実行に必要な時間が短いため、ビット操作の速度は算術演算よりも高速です。ビット操作は非常に高速に見えますが、ビット操作は多数の実行が行われた場合にのみ確認できます。運用上のメリット結局のところ、今日のコンピューターはますます高速になっています。