71

2 つの整数の符号が同じかどうかを確認する最も簡単な方法はどれですか? これを行うための短いビット単位のトリックはありますか?

4

19 に答える 19

227

どうしたの

return ((x<0) == (y<0));  

?

于 2008-09-15T22:06:19.607 に答える
52

これは、整数サイズに依存しない、またはオーバーフローの問題を抱えていない C/C++ で動作するバージョンです (つまり、x*y>=0 は動作しません)。

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 が異なる必要があるため、ゼロに対する異なるチェックが行われます。

于 2008-09-15T21:12:14.310 に答える
34
(a ^ b) >= 0

符号が同じ場合は 1、そうでない場合は 0 と評価されます。

于 2008-09-15T21:06:18.160 に答える
12

整数の符号を決定するためのビット単位のトリックには注意が必要です。その場合、これらの数値が内部でどのように表現されるかについて仮定する必要があるからです。

ほぼ 100% の場合、整数は2 の補数として格納されますが、特定の格納形式を保証するデータ型を使用していない限り、システムの内部について仮定することはお勧めできません。

2 の補数では、整数の最後の (一番左の) ビットをチェックして負かどうかを判断できるため、これら 2 つのビットだけを比較できます。これは、0 が正の数と同じ符号を持つことを意味しますが、これはほとんどの言語で実装されている符号関数と矛盾しています。

個人的には、選択した言語の符号関数を使用したいと思います。このような計算でパフォーマンスの問題が発生する可能性はほとんどありません。

于 2008-09-15T21:06:48.673 に答える
6

32 ビット整数を想定すると、次のようになります。

bool same = ((x ^ y) >> 31) != 1;

もう少し簡潔に:

bool same = !((x ^ y) >> 31);
于 2008-09-15T21:01:24.273 に答える
5

(整数 1 * 整数 2) > 0

2 つの整数が符号を共有している場合、乗算の結果は常に正になるためです。

何があっても同じ符号として 0 を扱いたい場合は、 >= 0 にすることもできます。

于 2008-09-15T21:01:46.470 に答える
5

「ビットごとのトリック」と「最も単純な」を同義語と見なすかどうかはよくわかりません。符号付きの 32 ビット整数を想定している回答がたくさんあります (ただし、符号なしを求めるのはばかげています) それらが浮動小数点値に適用されるかどうかはわかりません。

「最も簡単な」チェックは、両方の値が 0 とどのように比較されるかを比較することです。型を比較できると仮定すると、これはかなり一般的です。

bool compare(T left, T right)
{
    return (left < 0) == (right < 0);
}

符号が反対の場合は、false になります。符号が同じであれば、真になります。

于 2008-09-15T21:25:30.563 に答える
4

2の補数演算を仮定すると(http://en.wikipedia.org/wiki/Two_complement):

inline bool same_sign(int x, int y) {
    return (x^y) >= 0;
}

これは、最適化された最新のプロセッサでは、わずか2命令、1ns未満で済みます。

2の補数の算術を仮定しない:

inline bool same_sign(int x, int y) {
    return (x<0) == (y<0);
}

これには、1つまたは2つの追加の指示が必要で、少し時間がかかる場合があります。

乗算はオーバーフローに対して脆弱であるため、乗算を使用することはお勧めできません。

于 2008-09-15T22:45:33.757 に答える
3

(x * y) > 0 の場合...

非ゼロなどを想定しています。

于 2008-09-15T20:58:17.320 に答える
2

技術的な注意点として、最新のアーキテクチャであっても、ビット操作のソリューションは乗算よりもはるかに効率的です。節約できるのは約 3 サイクルだけですが、「ペニー節約」について彼らが何と言っているか知っています...

于 2008-09-15T21:04:56.680 に答える
1

頭のてっぺんから...

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;
于 2008-09-15T20:59:37.223 に答える
1

(a*b < 0) 符号が異なる場合、そうでなければ符号は同じ (または a または b がゼロ)

于 2008-09-15T21:00:12.420 に答える
1

ブランチレス 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));
}
于 2011-06-02T14:18:52.097 に答える
1

2 の補数演算による任意のサイズの int の場合:

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same
于 2008-09-15T21:15:32.740 に答える
1

32ビットを想定

if(((x^y) & 0x80000000) == 0)

...オーバーフローのため、答えif(x*y>0)は悪いです

于 2008-09-15T21:18:07.930 に答える
0

次のようにstd::signbitを使用するより良い方法:

std::signbit(firstNumber) == std::signbit(secondNumber);

他の基本型 ( 、 など) もサポートしてdoublefloatますchar

于 2015-12-01T22:16:58.890 に答える
0

int same_sign = !( (x >> 31) ^ (y >> 31) );

if ( same_sign ) ... else ...

于 2008-09-15T21:04:14.593 に答える
0

大学時代を思い出すと、ほとんどの機械表現では、整数の左端のビットは、負の場合は 1 であり、正の場合は 0 ではないでしょうか?

ただし、これはかなりマシンに依存していると思います。

于 2008-09-15T21:01:27.203 に答える