2つの整数の符号が同じかどうかを確認する最も簡単な方法はどれですか?これを行うための短いビットごとのトリックはありますか?
整数サイズに依存しない、またはオーバーフローの問題がある(つまり、x * y> = 0が機能しない)C/C++で動作するバージョンを次に示します。
bool SameSign(int x, int y)
{
return (x >= 0) ^ (y < 0);
}
もちろん、ギークアウトしてテンプレートを作成できます:
template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
return (x >= 0) ^ (y < 0);
}
注:排他的ORを使用しているため、符号が同じ場合はLHSとRHSを異なるものにしたいため、ゼロに対する異なるチェックを行います。
どうしたの
return ((x<0) == (y<0));
?
(a ^ b) >= 0
符号が同じ場合は1、それ以外の場合は0に評価されます。
整数の符号を決定するためのビット単位のトリックには警戒します。その場合、これらの数値が内部でどのように表現されるかについての仮定を行う必要があります。
ほぼ100%の時間、整数は two's compliment として保存されますが、特定のストレージ形式を保証するデータ型を使用している場合を除き、システムの内部について推測することは良い習慣ではありません。
2の賛辞では、整数の最後(左端)のビットをチェックして負であるかどうかを判断できるため、これら2つのビットだけを比較できます。これは、0が正の数と同じ符号を持つことを意味しますが、これはほとんどの言語で実装されている符号関数と対立します。
個人的には、選択した言語の手話機能を使用するだけです。このような計算でパフォーマンスの問題が発生する可能性はほとんどありません。
32ビット整数を想定:
bool same = ((x ^ y) >> 31) != 1;
少し簡潔:
bool same = !((x ^ y) >> 31);
「ビット単位のトリック」と「最も単純な」を同義語と見なすかどうかはよくわかりません。符号付き32ビット整数を前提とする多くの回答があります(ただし、would符号なしを要求するのはばかげています)。それらが浮動小数点値に適用されるかどうかはわかりません。
「最も簡単な」チェックは、両方の値が0と比較される方法を比較することです。これは、型を比較できると仮定するとかなり一般的です:
bool compare(T left, T right)
{
return (left < 0) == (right < 0);
}
符号が反対の場合、偽になります。兆候が同じであれば、あなたは真実になります。
(整数1 *整数2)> 0
2つの整数が符号を共有する場合、乗算の結果は常に正になるためです。
0を何であれ同じ符号として扱いたい場合は、0以上にすることもできます。
2の補数演算を想定( http://en.wikipedia.org/wiki/Two_complement ):
inline bool same_sign(int x, int y) {
return (x^y) >= 0;
}
これは、最適化された最新のプロセッサでは、わずか2命令で1ナノ秒未満で済みます。
2の補数演算を想定していない:
inline bool same_sign(int x, int y) {
return (x<0) == (y<0);
}
これには1つまたは2つの追加の指示が必要で、少し時間がかかる場合があります。
乗算の使用は、オーバーフローに対して脆弱であるため、悪い考えです。
if(x * y)> 0 ...
非ゼロなどを想定しています。
技術的な注意点として、ビットトゥワイズソリューションは、現代のアーキテクチャでも、乗算よりもはるかに効率的です。保存しているのは約3サイクルだけですが、「節約されたペニー」について彼らが言うことはわかっています...
ブランチレスCバージョン:
int sameSign(int a, int b) {
return ~(a^b) & (1<<(sizeof(int)*8-1));
}
整数型用のC++テンプレート:
template <typename T> T sameSign(T a, T b) {
return ~(a^b) & (1<<(sizeof(T)*8-1));
}
頭の上から.
int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;
2の補数演算を使用した任意のサイズのintの場合:
#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
// signs are the same
32ビットと仮定
if(((x^y) & 0x80000000) == 0)
...応答if(x*y>0)
はオーバーフローのために悪い
(a * b <0)符号が異なる場合、または符号が同じ(またはaまたはbがゼロ)
私の大学時代を振り返ってみると、ほとんどの機械表現では、整数の左端のビットは、数値が負の場合は1、正の場合は0ではありませんか?
ただし、これはかなりマシンに依存していると思います。
int same_sign =!((x >> 31)^(y >> 31));
if(same_sign)... else ...
次のように std :: signbit を使用するより良い方法:
std::signbit(firstNumber) == std::signbit(secondNumber);
また、他の基本型(double
、float
、char
など)もサポートしています。