-1

int は 2 の補数で 32 ビットであると想定できます。正当な演算子は次のとおりです。〜&^ | + << >>

この時点で、私はブルートフォースを使用しています

int a=0x01;
x=(x+1)>>1; //(have tried with just x instead of x+1 as well)
a = a+(!(!x));

... 最後の 2 つのステートメントが 32 回繰り返されます。これにより、x が 1 桁シフトされるたびに a に 1 が追加され、32 ビットすべてに対して != 0 になります。

テスト コンパイラを使用すると、テスト ケース 0x7FFFFFFF (0 の後に 31 個の 1 が続く) でメソッドが失敗し、この数値を表すには 32 ビットが必要であると表示されます。これが 31 ではない理由がわかりません (私の方法で計算します) 誰か理由を説明できますか? そして、これを説明するために何を変更する必要がありますか?

4

2 に答える 2

2

0x7FFFFFFF32ビットが必要です。わずか 31 ビットの符号なし整数として表現できます。

111 1111 1111 1111 1111 1111 1111 1111

しかし、それを 2 の補数を使用して符号付き整数として解釈すると、先頭1はそれが負であることを示します。したがって、先頭に を追加する必要があり0ます。

0 111 1111 1111 1111 1111 1111 1111 1111

これにより、32ビットになります。

何を変更する必要があるかについては、現在のプログラムには実際には未定義の動作があります。0x7FFFFFFF(2 31 -1) が最大許容整数値である場合、 は計算0x7FFFFFFF + 1できません。-2 32になる可能性がありますが、絶対的な保証はありません。標準では、この場合、コンパイラーは絶対に何でも行うことができます。実際、実際のコンパイラーは最適化を実行し、この要件に違反すると衝撃的な結果が生じる可能性があります。 . 同様に、 が負の場合に何... >> 1を意味するかについて具体的な保証はありません...が、この場合、コンパイラは少なくとも特定の動作を選択して文書化する必要があります。(ほとんどのコンパイラは、左端をコピーして別の負の数を生成することを選択します。1少しですが、それを保証するものではありません。)

したがって、実際に唯一の確実な修正は次のいずれかです。

  • これらの問題のないアルゴリズムを使用して、コード全体を書き直す。また
  • xであるケース0x7FFFFFFF(ハードコードされた を返す32) と負のケースx( に置き換えて~x-(x+1)通常どおり処理する)を具体的にチェックします。
于 2012-02-03T01:55:26.970 に答える
2

このコードを試して、符号付き整数xがnビットに収まるかどうかを確認してください。この関数は、一致する場合は 1 を返し、それ以外の場合は 0 を返します。

// http://www.cs.northwestern.edu/~wms128/bits.c
int check_bits_fit_in_2s_complement(signed int x, unsigned int n) {
  int mask = x >> 31;

  return !(((~x & mask) + (x & ~mask))>> (n + ~0));
}
于 2013-04-19T13:00:51.697 に答える