Frage

Welches ist der einfachste Weg, um zu überprüfen, ob zwei ganze Zahlen gleiche Vorzeichen haben? Gibt es einen kurzen bitweise Trick, dies zu tun?

War es hilfreich?

Lösung

Hier ist eine Version, die in C / C ++ arbeitet, die auf Integer-Größen nicht verlassen oder das Überlaufproblem haben (das heißt x * y> = 0 nicht funktioniert)

bool SameSign(int x, int y)
{
    return (x >= 0) ^ (y < 0);
}

Natürlich können Sie Aussenseiter und Vorlage:

template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
    return (x >= 0) ^ (y < 0);
}

. Hinweis: Da wir verwenden ausschließlich oder wollen wir die LHS und RHS, anders zu sein, wenn die Vorzeichen gleich sind, damit die unterschiedliche Prüfung gegen Null

Andere Tipps

Was ist los mit

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

(a ^ b) >= 0

wird auf 1 bewerten, wenn das Vorzeichen gleich ist, sonst 0.

Ich würde irgend bitweise Tricks vorsichtig sein, das Zeichen von ganzen Zahlen, um zu bestimmen, wie dann muss man Annahmen darüber, wie diese Zahlen macht intern dargestellt.

Fast 100% der Zeit, werden ganze Zahlen als Zweierkomplement- gespeichert werden, aber es ist nicht gute Praxis Annahmen über die Interna eines Systems zu machen, wenn Sie einen Datentyp verwenden, der ein bestimmtes Speicherformat guarentees.

In Zweier-Komplementen, können Sie überprüfen gerade den letzten (ganz links) Bit in der ganzen Zahl zu bestimmen, ob es negativ ist, so kann man nur diese beiden Bits vergleichen. Dies würde bedeuten, dass 0, obwohl das gleiche Vorzeichen als positive Zahl haben würde, die im Widerspruch mit der Zeichenfunktion in den meisten Sprachen implementiert ist.

Persönlich würde ich nur die Zeichenfunktion der von Ihnen gewählten Sprache. Es ist unwahrscheinlich, dass es keine Probleme mit der Leistung einer Berechnung sein wie diese.

Unter der Annahme, 32 Bit ints:

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

Etwas mehr lapidar:

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

Ich bin nicht wirklich sicher, ob ich „bitweise Trick“ betrachten würde und „einfachste“ synonym sein. Ich sehe eine Menge von Antworten, die 32-Bit-Integer unterzeichnet davon aus (obwohl es würde dumm für nicht signierten fragen); Ich bin nicht sicher, dass sie in Fließkommawerte gelten würden.

Es scheint, wie die „einfachste“ Kontrolle wäre zu vergleichen, wie beiden Werte auf 0 zu vergleichen; Das ist ziemlich allgemein die Typen unter der Annahme verglichen werden kann:

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

Wenn die Vorzeichen entgegengesetzt sind, erhalten Sie falsch. Wenn die Vorzeichen gleich sind, erhalten Sie wahr.

(integer1 * integer2)> 0

Weil, wenn zwei ganze Zahlen ein Zeichen teilen, wird immer das Ergebnis der Multiplikation positiv sein.

Sie können es auch machen> = 0, wenn Sie 0 als das gleiche Vorzeichen egal behandeln wollen, was.

Unter der Annahme, Zweier-Komplement-Arithmetik ( http://en.wikipedia.org/wiki/Two_complement):

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

Dies kann so wenig wie zwei Befehle nehmen und weniger als 1 ns auf einem modernen Prozessor mit Optimierung.

Nicht unter der Annahme, Zweier-Komplement-Arithmetik:

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

Dies kann eine oder zwei zusätzliche Anweisungen erfordern und ein wenig länger dauern.

Mit Multiplikation ist eine schlechte Idee, weil sie anfällig für Überlauf ist.

if (x * y)> 0 ...

unter der Annahme nicht Null und so weiter.

Als technischer Hinweis, Bit-twiddly Lösungen werden als Multiplikation wesentlich effizienter sein, auch auf moderne Architekturen. Es ist nur etwa 3 Zyklen, die Sie speichern, aber Sie wissen, was sie von einem „Penny gespeichert“ sagen ...

Direkt an der Spitze von meinem Kopf ...

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;

branchless C-Version:

int sameSign(int a, int b) {
    return ~(a^b) & (1<<(sizeof(int)*8-1));
}

C ++ Template für Integer-Typen:

template <typename T> T sameSign(T a, T b) {
    return ~(a^b) & (1<<(sizeof(T)*8-1));
}

Für jede Größe von int mit Zweier-Komplement-Arithmetik:

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same

unter der Annahme, 32-Bit-

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

... die Antwort if(x*y>0) ist schlecht wegen Überlauf

if (a * b <0) Zeichen anders, sonst Zeichen sind das gleiche (oder a oder b ist Null)

Denken wir zurück an meine Studienzeit in den meisten Maschinendarstellungen, ist nicht die am weitesten links stehende Bit einer ganzen Zahl a 1, wenn die Zahl negativ ist, und 0, wenn es positiv ist?

Ich stelle mir das ist eher maschinenabhängig, though.

!

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

if (same_sign) ... else ...

Bessere Art und Weise unter Verwendung von std :: Vorzeichenbit wie folgt:

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

Es auch andere Grundtypen unterstützen (double, float, char usw.).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top