2016-10-29 8 views
5

私はこのコードに出くわした:このmin()関数はどのように機能しますか?

int __min(int a, int b) { 
    return ((a)-(((a)-(b))&((b)-(a))>>31)); 
} 

私はそれが2の補数とは何かを持っており、それが唯一の符号付き32ビット整数のために動作しますが、その後、私は迷ってしまいましたことをことを想像することができます。

私はthis questionを見つけましたが、機能が関連しているとは思いませんか、間違っていますか?

だから私は2つの質問があります。この機能は動作しないのはなぜ

  1. を?
  2. (a<b)?a:bが機能しない可能性があります。この機能は、この機能か、この機能が楽しいために複雑すぎるのでしょうか?

EDIT:機能はGPUのために書かれているので、私は@Banex分岐を避けるためにされて、このようにそれを書くことの目的について権利かもしれないと思います。

+5

私は正確さを保証することはできませんが、私は、この機能の主なポイントは、分岐を避けるためです想像することができます。 – Banex

+1

@Banexこの関数はgpu用に書かれていますが、これは意味があると思います、良い点です! –

+1

また、実質的に整数オーバーフローを含むパスを最適化することができ –

答えて

2

これは32ビット符号付き値で機能するように設計されています。これを一度に一歩踏み外しましょう。

((b)-(a))>>31) 

右シフト演算は、基本的に32ビット値の最上位ビットを取り、残りの31ビットを符号拡張。右シフト演算子は、符号付きの値に対してどのように動作するのですか。 baより大きい場合、減算の結果が肯定的となり、最上位ビットが0になり

、及びb未満a、の結果である場合、この結果は0

あります減算は負になり、最上位ビットは1になり、結果は-1になります。最上位のビットは、残りのすべてのビットにシフトされます。 32ビット値のすべてのビットが設定され、-1になります。

正の値または負の値のいずれかを32ビットのintに置き、31ビット右にシフトするショートプログラムを作成して、これを確認することができます。結果が0または-1のいずれかになることを観察します。ご存じのように、2の補数演算では、値-1にはすべてのビットが設定されています。

((a)-(b)) & (0 or -1, as the result of the previous operation). 

b未満aであれば、右辺値は、すべてのビットセット、およびビット単位&オペレータが左側の値である結果を有します。またはa-b

bより大きい場合、a右側の値はすべてビット0を持ち、&の結果は0です。結論として

b未満aであれば、上記の式は、と評価されます

a-(a-b) 

or 

a-a+b 

or 

b 

そしてbaよりも大きい場合、式の結果は

a - 0 

or 

a 
です
0

表現

> B、および
0 

そう

にので、もし、それが最終的にから減算されている場合
((a)-(b))&((b)-(a))>>31 

はほとんど余分括弧なし

(a - b) & (b - a) >> 31 

a - b 

に評価すなわちそれは

と同じです
if (a > b) 
    return (a - (a - b)); 
else 
    return (a - 0); 
関連する問題