6

私は、lareValue1 と largeValue2 のすべての可能な値 (これらは少なくとも 1 です) を含む正の数を alwaysPositive に割り当てたいと考えています。

次のステートメントは、バッファ オーバーフローを引き起こします。

int alwaysPositive = (largeValue1 + largeValue2) / 2;

減算して追加することでそれを防ぐことができることを私は知っています:

int alwaysPositive = largeValue1 + ((largeValue2 - largeValue1) / 2);

しかし、他のプログラミング言語では、符号なしビットシフトを使用してトリックを実行できます。

int alwaysPositive3 = (largeValue1 + largeValue2) >>> 1;

C#でこれを行うにはどうすればよいですか?


以下の答えはすべて問題を解決します。これを行う方法はおそらくたくさんありますが、それらすべて (私の解決策を含む) には共通点が 1 つあります。

4

6 に答える 6

3
int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + (largeValue1 & largeValue2 & 0x01);

上記の背後にある考え方は、結果を追加する前に結果を事前に分割すると、両方の上位ビットが設定解除されるため、オーバーフローを回避できるということです。次に、わずかな修正ロジックを追加して、両方が正の場合 (切り捨て) に値を 1 増やします。どちらかが正であるかどうかのみを気にする場合 (四捨五入)、次のように変更できます。

int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + ((largeValue1 | largeValue2) & 0x01);
于 2008-09-22T21:10:32.823 に答える
3

unchecked((largeValue1 + largeValue2) >> 1)別のオプションです。

unchecked キーワードのドキュメントを参照してください。

于 2008-09-22T21:48:43.840 に答える
2

次の方法で実行できます。

  x = largeValue1;
  y = largeValue2; 
  return (x&y)+((x^y)/2);

これは、オーバーフローなしで 2 つの整数の平均を取得するための少し手間のかかる方法です。

必要に応じて、2 による除算をビット シフトに置き換えることができますが、とにかくコンパイラがそれを行います。

于 2008-09-22T20:48:36.090 に答える
0

uintを使用できます:

uint alwaysPositive = (uint)(largeValue1 + largeValue2) / 2;
于 2008-09-22T20:45:25.023 に答える
0

つまらないことではありませんが、「バッファオーバーフロー」ではなく「整数オーバーフロー」を意味します。

私は C# を知らないので、別の方法があるかもしれませんが、最上位ビットをマスクするだけで符号なしシフトを模倣できます: (x >> 1) & 0x80000000

于 2008-09-22T20:46:13.397 に答える
0
try
{
    checked { alwaysPositive3 = (largeValue1 + largeValue2); }
}
catch (OverflowException ex)
{
   // Corrective logic
}
于 2008-09-22T21:38:27.920 に答える