18

unsigned で算術演算を実行したいのですが、負の int の絶対値を取得する必要があります。

do_some_arithmetic_in_unsigned_mode(int some_signed_value)
{
   unsigned int magnitude;
   int negative;
   if(some_signed_value<0) {
       magnitude = 0 - some_signed_value;
       negative = 1;
    } else {
       magnitude = some_signed_value;
       negative = 0;
    }
   ...snip...
}

ただし、INT_MIN は問題になる可能性があります。符号付き演算で実行される場合、0 - INT_MIN は UB です。Cでこれを行う標準/堅牢/安全/効率的な方法は何ですか?

編集:

2 の補数であることがわかっている場合、暗黙のキャストと明示的なビット演算が標準になるのでしょうか? 可能であれば、この仮定を避けたいと思います。

do_some_arithmetic_in_unsigned_mode(int some_signed_value)
{
   unsigned int magnitude=some_signed_value;
   int negative=some_signed_value<0;
   if (negative) {
       magnitude = (~magnitude) + 1;
    }
   ...snip...
}
4

5 に答える 5

26

符号付きから符号なしへの変換は明確に定義されています。対応する代表モジュロ 2 Nを取得します。したがって、以下は の正しい絶対値を示しますn

int n = /* ... */;

unsigned int abs_n = n < 0 ? UINT_MAX - ((unsigned int)(n)) + 1U
                           : (unsigned int)(n);

更新: @aka.nice が示唆するように、実際には次のように置き換えることができUINT_MAX + 1Uます0U

unsigned int abs_n = n < 0 ? -((unsigned int)(n))
                           : +((unsigned int)(n));
于 2012-09-01T21:36:14.217 に答える
6

マイナスの場合は をとりsome_signed_value+1ます。それを否定します (これは にならないので安全ですINT_MIN)。署名なしに変換します。次に、1 つ追加します。

于 2012-09-01T21:49:45.833 に答える
2

はいつでもテストできます>= -INT_MAX。これは常に明確に定義されています。あなたにとって興味深い唯一のケースは、 ifINT_MIN < -INT_MAXと thatsome_signed_value == INT_MINです。その場合は個別にテストする必要があります。

于 2012-09-01T21:36:29.137 に答える