4
int mystery(int x, int n)
{
   return (x + (x>>31 & ((1 << n) + ~0))) >> n;
}

このコードがどのように機能するかを理解しようとしています。これは私がこれまでに持っているものです:

  • n を 1 だけ左にシフトし、
  • その結果を 1^32 に追加します (なぜ?)
  • この結果は、x が 31 にシフトされます (これは x>>31 の値をクリアするだけではありませんか?)
  • n だけシフトする直前に x を追加します (繰り返しますが、理由がわかりません)。
4

1 に答える 1

11

正しい丸め (ゼロに向かって丸める) を使用して 2^n で除算するため、式は次のようになります。

y = x / (1 << n);

2^n による除算に単純なアプローチを取る場合、つまり

y = x >> n;

x < 0 の丸めは正しくありません。

式のこの部分: (x>>31 & ((1 << n) + ~0))x >= 0 の場合は 0 ですが、x < 0 の場合は 2^n - 1 を加算して結果を適切に調整します。

厳密に言えば、式は実装固有の動作に依存することに注意してください。これは、符号付き整数を右シフトすると符号ビットが保持されることを前提としているためです。これはほとんどのコンパイラとプラットフォームに当てはまりますが、保証できないため、式は 100% 安全または移植可能ではありません。

また、この式には int が 32 ビットであるというハードコーディングされた前提があり、これも移植性がないことに注意してください。任意のサイズの int で動作する、より移植性の高いバージョンは次のようになります。

   return (x + (x >> (sizeof(int) * CHAR_BIT - 1) & ((1 << n) + ~0))) >> n;
于 2013-09-24T14:54:11.463 に答える