Integer.highestOneBit(i)の詳細



Integer Highestonebit Detailed



HashMapのソースコードを表示する過程で、それが使用されていることがわかりました

Integer.highestOneBit(i)
この関数が呼び出されます。最初の使用感は、この機能の目的です。ドキュメントを見ると、この関数の機能は、数値iの左端の2進数形式の最上位ビットを取得し、上位ビットの後のすべてのゼロを埋め、最後にint型の結果を返すことであることがわかります。



最初に少し背景知識を追加しましょう。

1.コンピュータシステムでは、値は常に補数で表され、保存されます。主な理由は、符号ビットと他のビットを補数コードを同時に使用することで均一に処理でき、減算も加算として処理できるためです。また、補数で表した2つの数値を加算した場合、最上位ビット(符号ビット)に桁上げがあると、桁上げは破棄されます。
-補完コードと元のコードの間の変換プロセスはほとんど同じです。
-値の補数(2つのタイプ)
-正の数の補数:元のコードと同じ
-負の数の補数:符号ビットは1で、残りのビットの絶対値の元のコードが反転され、整数が1増加します。
-数の補数を知っているので、元のコードを見つける操作は2つのケースに分けられます
-補数コードの符号ビットが「0」の場合、それは正の数であることを意味するため、補数コードはその数の元のコードです。
-補数コードの符号ビットが「1」の場合、それは負の数であることを意味します。元のコードを見つける操作は次のようになります。符号ビットは1で、他のビットは反転され、整数は1ずつ増加します。
2.シフト演算子は、2進数に基づいて数値を変換します。 Javaは、翻訳の方向と数字の入力規則に従って3つのタイプに分けられます。<>符号付きの右シフトと>>>符号なしの右シフト。
3. Javaシフト演算では、byte、short、およびchar型をシフトした結果はint型になります。 byte、short、char、およびintをシフトする場合、char、short、char、およびintに対してシフト操作を実行する場合、実際のシフト数はシフト数であり、残りの32、つまり結果であると指定されます。 33回シフトすることと1回シフトすることは同じです。長い値を移動する場合、実際の移動数は移動数と余り64であると指定されます。つまり、65回シフトして1回シフトしても同じ結果が得られます。
(1)<< Operation rule: According to the binary form, move all the numbers to the left by the corresponding number of bits, shift out the high bits (discard), and fill the low bits with zeros.
構文形式:
シフトする数<例:4<<2, then the number 4 is shifted to the left by 2 digits
計算プロセス
4<<2
Javaでは、整数は4バイトを占め、4の2進数は00000000 00000000 00000000 00000100であり、数値は2つ左にシフトされます。他の数値は2ビット右にシフトされ、最後にゼロが下(右)の位置にある2つのスペースに追加されます。最終結果は000000000000000000000000 00010000で、10進数16に変換されます。
数値がオーバーフローしないという前提の下で、正と負の数値の場合、1ビットを左にシフトすることは2の累乗を乗算することと同等であり、nビットを左にシフトすることは2を乗算することと同等です。 。
このルールに準拠していないオーバーフローの前に進みます。読者は(長い)1610612736 * 4と1610612736を出力してみることができます<<2 for comparison.
(2)>>操作規則:バイナリ形式に従って、すべての数値が右の対応する位置に移動され、下位がシフトアウト(破棄)され、上位のスペースが符号ビット、つまり正で埋められますゼロ、負の数の場合は1を補完します。
構文形式:
シフトする数>>シフト数
例:-4 >> 2および4 >> 2の場合、数値-4および4は右に2桁シフトされます。
計算プロセス
4 >> 2
Javaでは、intの数値は4バイトを占め、4の2進数は00000000 00000000 00000000 00000100であり、数値は2ビット右にシフトされます。他の数値は2ビット左にシフトされ、最後に符号ビットが上位に追加され(数値は正で、すべてゼロが追加されます)、結果は00000000 00000000 00000000 00000001になります(10進数が1.数学的な意味は、右シフトは2で除算することと同等であり、nビットで右シフトすることは2でnの累乗で除算することと同等です。
4 >> 2
負の数はコンピューターに補数の形式で格納されるため、-4の2進数は11111111 11111111 11111111 11111100になり、数値を2桁右に、他のすべての数値を左に2ビット、最後に符号をシフトします。上位ビットのビット(数値は負、完全な補数1)の場合、結果は11111111 11111111 11111111 11111111(補数形式)になり、10進数で-1になります。
(3)>>>操作規則:バイナリ形式に従って、すべての数値を対応するビット数だけ右に移動し、下位ビットをシフトアウト(破棄)して、上位ビットにゼロを入力します。正の数の演算の結果は、符号付き右シフトと同じですが、負の数の場合は異なります。
4 >>> 2および-4 >>> 2の操作の場合、上記の例から類推できます。



Javaのビット演算を理解した後、Integer.highestOneBit(i)の実装コードを見てみましょう。

public static int highestOneBit(int i) = (i >> 1) // equivalent to i = i

1.最初のステップの機能は、最上位ビット1を右にシフトし、元のデータとビット単位のORをとることです。次に、これにより最上位ビットとその次の2つの連続するビットが作成されます。
2. 2番目のステップの機能は、右に2ビットシフトして得られた2つの連続する1を移動し、元のデータとビット単位のORをとることです。次に、これにより上位2ビットが作成され、次の2つの連続するビットが4つの連続する1を形成します。
3.類推により、最後のiは、最初から最後までの最上位ビットからすべて1です。そして、i unsigned right shiftを1ビット引くと、intデータの最上位ビットの値を取得できます。
4.上記の状況は、iがゼロではなく負の場合です。 iがゼロの場合、結果は常にゼロになります。 iが負の数の場合、結果は常に-2147483648になります。これはInteger.MIN_VALUEと同じです。 (理由は、負の数の最上位ビットが常に1であり、これが負の数の符号ビットであるためです)

この関数を理解する上で最も重要な点は、算術処理のためにバイナリの最上位ビットを常に把握することです。関数の右シフトは1、2、4、8、16です。理解しやすいです。同様に、long型の最上位演算の場合、Javaではlong型が64ビットであるため、文i | =(i >> 32)を追加する必要があります。
Long型のLongestOneBit(i)のコードは次のとおりです。

public static long highestOneBit(long i) = (i >> 16) i