abs関数もifステートメントも使用せずに絶対値を取得する

2012年03月19日に質問されました。  ·  閲覧回数 86.8k回  ·  ソース

shanwu picture
2012年03月19日

ifステートメントもabs()も使用せずに、整数の絶対値を取得する方法を考えていました。 最初は左シフトビット( << )を使用して、範囲外の負の符号を取得しようとしてから、ビットを右にシフトして元の位置に戻しましたが、残念ながら機能しません。 それが機能しない理由とそれを行う他の代替方法を教えてください。

回答

Hasturkun picture
2012年03月19日
45

Bit Twiddling Hacksから:

int v;           // we want to find the absolute value of v
unsigned int r;  // the result goes here 
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

r = (v + mask) ^ mask;
perreal picture
2012年03月19日
30
int abs(int v) 
{
  return v * ((v>0) - (v<0));
}

このコードは、 vの値に-1または1を掛けて、abs(v)を取得します。 したがって、括弧内は-1または1ます。

vが正の場合、式(v>0)はtrueであり、値は1(v<0)はfalseになります(falseの場合は値0)。 したがって、 vが正の場合((v>0) - (v<0)) = (1-0) = 1 。 そして、全体の式は次のとおりです。 v * (1) == v

vが負の場合、式(v>0)は偽であり、値は0(v<0)は真(値1)になります。 したがって、負のv場合、 ((v>0) - (v<0)) = (0-1) = -1 。 そして、全体の式は次のとおりです。 v * (-1) == -v

v == 0場合、 (v<0)(v>0)両方が0と評価され、 v * 0 == 0残ります。

Sebastian Mach picture
2012年03月19日
22

ブランチレス:

int abs (int n) {
    const int ret[2] = { n, -n };
    return ret [n<0];
}

注4.7積分変換/ 4: [...] If the source type is bool, the value false is converted to zero and the value true is converted to one.

Quản B&#225; Hồng Nguyễn picture
2017年09月07日
10

このコードをCで試してみると、うまくいきます。

int abs(int n){
   return n*((2*n+1)%2); 
}

この回答がお役に立てば幸いです。

flanglet picture
2012年04月01日
8

32ビットの符号付き整数(Java)を想定すると、次のように記述できます。

public static int abs(int x)
{
    return (x + (x >> 31)) ^ (x >> 31);
}

乗算も分岐もありません。

ところで、 return (x ^ (x >> 31)) - (x >> 31);も同様に機能しますが、特許を取得しています。 うん!

注:このコードは、条件文(8ビットVerison)よりも10倍以上長くかかる場合があります。 これは、ハードウェアプログラミングシステムCなどに役立つ場合があります。

Jeremy picture
2013年01月23日
5

次のことを試してください。

int abs(int n) 
{
  return sqrt(n*n);
}
Kerrek SB picture
2012年03月19日
2

あなたが考える方法で符号付き整数をビットシフトすることは未定義の振る舞いであり、したがってオプションではありません。 代わりに、これを行うことができます:

int abs(int n) { return n > 0 ? n : -n; }

ifステートメントはなく、条件式のみです。

dewang picture
2013年09月21日
2

論理式/条件式がない場合、 abs()ない別のアプローチを次に示します。ここでは、intが32ビット整数であると想定します。 考え方は非常に単純です。 (1 - 2 * sign_bit)sign_bit = 1 / 0 to -1 / 1を変換します。

unsigned int abs_by_pure_math( int a ) {
   return (1 - (((a >> 31) & 0x1) << 1)) * a;
}
MAG picture
2015年10月15日
2

これを見なかった。 2の補数表現と32ビット整数の場合

( n >> 31 | 1 ) * n
Dani Barca Casafont picture
2017年09月06日
2

あなたの言語がboolがintキャストを許可している場合(C / C ++のように):

float absB(float n) {
    return n - n * 2.0f * ( n < 0.0f );
}