4

宿題のために、2 つの符号付き整数を加算する関数を C で作成する必要がありますが、正のオーバーフローの場合は INT_MAX を返し、負のオーバーフローの場合は INT_MIN を返します。使用できる演算子について、非常に厳しい制限に従う必要があります。すべての整数は 2 の補数形式であり、右シフトは算術演算であり、整数サイズは可変です (sizeof(int)<<3 で見つけることができます)。条件、ループ、比較演算子、またはキャストを使用できません。ビット演算子と論理演算子、加算と減算、等値テスト、および整数定数 INT_MAX と INT_MIN のみを使用できます。

2 つの入力の符号が同じで、結果の符号が異なる場合、オーバーフローを検出できることがわかっています。方程式がオーバーフローしたかどうかを示すフラグがあるところまで来ました。そこから最終製品にたどり着く方法がわかりません。これは私がこれまでに持っているものです:

int saturating_add(int x, int y){
    int w = sizeof(int)<<3;
    int result = x+y;
    int signX = (x>>w-1)&0x01;//Sign bit of X
    int signY = (y>>w-1)&0x01;//Sign bit of Y
    int resultSign = (result>>w-1)&0x01; //Sign bit of result
    int canOverflow = ~(signX ^ signY); //If they're the same sign, they can overflow
    int didOverflow = (resultSign^signX)&canOverflow; //1 if input signs are same and result sign different, 0 otherwise

}

私はC (HW) でのビット単位の飽和加算に示されている答えに従おうとしていますが、符号ビット以外のすべてに対して同じビットで整数を埋めなければならない部分に行き詰まっています (1 は 0111 になります。 .11 と 0 は 0000.00 になります)。「シフトとORの組み合わせ」がどうなるかわかりません。

4

1 に答える 1

2

あなたは答えを誤解していると思います。すべきことは、符号ビットをMSB を含むすべてのビットに拡張することです。これは、符号ビットを保持する int を取得し、didOverflowその補数に 1 を追加することで実現できます。

次に、オーバーフローが発生した場合に返されるオーバーフロー値を見つけます。INT_MAXこれは、extendedを XOR することで実行できますsignX(またはsignY、両方とも機能します)。この値を としましょうoverflow。最後に、次のように変更overflowresultます。

overflow := (extended didOverflow) AND overflow
result := (NOT (extended didOverflow)) AND result

これらの割り当ての後、拡張didOverflowが 1...1の場合、overflow明らかに変更されません。result一方、 は 0 になります。

しかし、didOverflowis が 0...0 の場合、反対のことが適用されます。isoverflowは現在 0 ですが、result変更されません。

最初のケース ( didOverflowwas は 1...1 で、オーバーフローがあったことを示しています) では、overflow OR resultequals overflow. 2 番目のケース (オーバーフローがない場合) では、overflow OR resultequals result. いずれoverflow OR resultにせよ、正しい値が得られます。

于 2013-10-07T01:28:55.417 に答える