0

1 バイトに設定されたビット数を数えようとしていますが、答えが見つからない問題が発生しているようです。

私のコードは現在次のようになっています

   public static int numBits(byte input){
       int count = 0;
       while (input != 0){
           if ((input & 1)==1){
               count++;
           }
           input >>= 1;
       }
       return count;
   }

私が試すまではうまくいくように見えましたx = -1

これにより、値 1 のビットが挿入されるため、無限ループが作成されました。だから私はつまずいた

Java: 負の数の右シフト

私の解釈では、これを使用する必要があることを意味していましinput >>>= 1;たが、これでも無限ループが発生しました。

だから私は試してみて、何が起こっているのかを理解しようとしました

byte x = -1;
System.out.println(x >>> 1);
System.out.println(x >> 1);

につながる

2147483647
-1

私をもっと混乱させます。番号はどこ2147483647から来たのですか?どこで論理的な間違いを犯している可能性がありますか?

4

3 に答える 3

3

これはすべて、符号付き整数をバイナリ値として格納する方法が原因です。数値の最上位ビットが符号を決定する方法 (一種のゼロは物事を奇妙にします) であり、符号は算術シフトで保持されていました。int結果がバイトではなく値に昇格されているため、print ステートメントは奇妙な結果を示しています。

これを本当に簡単に修正したい場合は、 an を使用しintて値を保存できますが、最下位バイト以外はすべてマスクしてください。

public static int numBits(byte inByte){
   int count = 0;
   int input = inByte & 0xFF;
   while (input != 0){
       if ((input & 1)==1){
           count++;
       }
       input >>= 1;
   }
   return count;
}

上記のコメントで述べたように、バイナリでの符号付き数値の 2 の補数表現について実際に読む必要があります。負の数がどのように表されるか、および算術シフトと論理シフトの違いを理解していれば、そのすべてが完全に理にかなっています。

于 2013-09-13T03:23:38.053 に答える
1

JVM が実際にどのようにそれを行うのか興味深いことに気付くかもしれません。注: 8 ビットしかないので、実際にはループは必要ありません。

public static int bitCount(int i) {
    // HD, Figure 5-2
    i = i - ((i >>> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
    i = (i + (i >>> 4)) & 0x0f0f0f0f;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    return i & 0x3f;
}

注: x86/x64 では、JVM はこれを組み込みに置き換えます。つまり、単一のマシン コード命令を使用します。このメソッドをコピーして比較すると、JVM はハードコードされたメソッドのリストのみを置き換えるため、元のメソッドの呼び出しは 3 倍遅くなり、Integer.bitCOunt は置き換えられますが、コピーは置き換えられません。

つまり、再発明するのではなく、組み込みのメソッドを使用します。

于 2013-09-13T07:32:31.340 に答える