Welcher ist der einfachste Weg zu prüfen, ob zwei ganze Zahlen das gleiche Vorzeichen haben? Gibt es dafür einen kurzen, bitweisen Trick?Der einfachste Weg zu prüfen, ob zwei ganze Zahlen das gleiche Vorzeichen haben?
Antwort
Hier ist eine Version, die in C/C++ arbeitet, die nicht auf ganzzahlige Größen angewiesen ist oder das Überlaufproblem haben (dh x * y> = 0 nicht funktioniert)
bool SameSign(int x, int y)
{
return (x >= 0)^(y < 0);
}
Natürlich Sie können und Vorlage Aussenseiter:
template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
return (x >= 0)^(y < 0);
}
Hinweis: Da wir ausschließlich oder verwenden, wir wollen, dass die LHS und die RHS, anders zu sein, wenn die Vorzeichen gleich sind, so dass die unterschiedliche Prüfung gegen Null.
if (x * y)> 0 ...
ungleich Null und eine solche anzunehmen.
Direkt an der Spitze von meinem Kopf ...
int mask = 1 << 31;
(a & mask)^(b & mask) < 0;
funktioniert nur für 32-Bit-Ints, die nicht –
wenn (a * b < 0) Zeichen anders, sonst Zeichen gleich sind (oder a oder b ist Null)
in der Frage festgelegt wurde, stimmt für den Schwall –
Unter der Annahme, 32-Bit-Ganzzahlen:
bool same = ((x^y) >> 31) != 1;
etwas mehr terse:
bool same = !((x^y) >> 31);
Diese beiden Codebeispiele sollten immer immer immer durch einen Code Kommentar vorangestellt werden nicht funktionieren, bitte (im wirklichen Leben) –
Oh, natürlich . Im wirklichen Leben würde ich wahrscheinlich etwas Ähnliches verwenden = Math.Sign (x) == Math.Sign (y). Ich gebe nur böse Bitwidilösungen, wenn Leute danach fragen. : D – Patrick
Ähm, das ist kein gültiger Code ... wie soll '' 'funktionieren? –
Denken Sie zurück zu meinen Universitätstagen, in den meisten Maschinendarstellungen, ist nicht das äußerste linke Bit einer ganzen Zahl a 1, wenn die Zahl negativ ist, und 0, wenn es positiv ist?
Ich stelle mir vor, dass dies eher maschinenabhängig ist.
(integer1 * integer2)> 0
Denn wenn zwei ganzen Zahlen ein Zeichen teilen, wird immer das Ergebnis der Multiplikation positiv sein.
Sie können es auch> = 0 machen, wenn Sie 0 als gleiches Zeichen behandeln wollen, egal was passiert.
Funktioniert nur bis das Produkt überläuft. – Frosty
auch, Multiplikation könnte eher langsam sein ... –
Wenn eine der ganzen Zahlen 0 sind, dann haben Sie ein Problem. – TatiOverflow
int gleich_sign =! ((X >> 31)^(y >> 31));
if (same_sign) ... sonst ...
Als technischer Hinweis, Bit-twiddly Lösungen werden wesentlich effizienter als Multiplikation sein, auch auf modernen Architekturen. Es ist nur etwa 3 Zyklen, die Sie speichern, aber Sie wissen, was sie von einem „Penny gespeichert“ sagen ...
Ein gesparter Penny ist die Wurzel allen Übels, sagen wir etwa 97% der Zeit? – ysth
(a^b) >= 0
zu 1 bewerten, wenn das Vorzeichen gleich, sonst 0 ist.
Oh, schön! :-) Ich bin überrascht, dass ich diese verpasst habe. Das wirklich Schöne an dieser Lösung ist, dass sie nicht von einer bestimmten Bit-Kardinalität in der zugrundeliegenden Integer-Darstellung abhängt. –
Dies führt zu der herrlich kompakten "xorl% edi,% esi; setzt% al" auf x86, nur 6 Bytes und zwei Anweisungen. Es ist auch eine interessante Fallstudie, da es sich um einen konkreten Fall handelt, in dem die Rückgabe eines "Bool" anstelle eines Int einen dramatisch besseren Code liefert. –
@JohnMeacham: Ich frage mich, was Sie meinen, es ist ein konkreter Fall, in dem die Rückgabe eines 'Bool' anstelle eines Int einen dramatisch besseren Code ergibt. ' –
Ich wäre vorsichtig mit irgendwelchen bitweisen Tricks, um das Vorzeichen von ganzen Zahlen zu bestimmen, da dann Annahmen getroffen werden müssen, wie diese Zahlen intern dargestellt werden.
Fast 100% der Zeit, werden ganze Zahlen als two's compliment gespeichert werden, aber es ist keine gute Praxis Annahmen über die Interna eines System zu machen, wenn Sie einen Datentyp, der ein bestimmtes Speicherformat guarentees verwenden.
Im Zweierkomplement können Sie einfach das letzte (am weitesten links liegende) Bit in der ganzen Zahl überprüfen, um festzustellen, ob es negativ ist, so dass Sie nur diese zwei Bits vergleichen können. Dies würde bedeuten, dass 0 das gleiche Vorzeichen haben würde wie eine positive Zahl, was im Widerspruch zu der Zeichenfunktion steht, die in den meisten Sprachen implementiert ist.
Persönlich würde ich nur die Zeichenfunktion der von Ihnen gewählten Sprache verwenden. Es ist unwahrscheinlich, dass es bei einer Berechnung wie dieser Leistungsprobleme geben würde.
Für jede Größe von int mit Komplement-Arithmetik der beiden:
#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
ich bin mir nicht wirklich sicher ob ich "bitweises trick" und "einfachste" auch bedenke. Ich sehe viele Antworten, die signierte 32-Bit-Ganzzahlen annehmen (obwohl es würde albern sein, nach unsigned zu fragen); Ich bin nicht sicher, ob sie sich auf Fließkommawerte beziehen würden.
Es scheint, als wäre die "einfachste" Überprüfung, zu vergleichen, wie beide Werte mit 0 verglichen werden; Das ist ziemlich allgemein die Typen verglichen werden kann unter der Annahme:
bool compare(T left, T right)
{
return (left < 0) == (right < 0);
}
Wenn die Vorzeichen entgegengesetzt sind, erhalten Sie falsch. Wenn die Zeichen die gleichen sind, werden Sie wahr.
false && false == false Ich befürchte, dass Sie die Negation eines XOR machen müssen, um es korrekt zu machen. –
Was mit
return ((x<0) == (y<0));
falsch?
Um ... Nichts ... Traurig, dass wir alle die einfache Lösung verpasst haben. – Torlack
Große Antwort, Einfachheit ist wunderbar. –
Was ist mit Signed Zero. -0.0 vs Unsigned Null 0.0 –
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 davon aus Zweier-Komplement-Arithmetik:
inline bool same_sign(int x, int y) {
return (x<0) == (y<0);
}
Diese eine oder zwei zusätzliche Anweisungen erfordern und ein wenig länger dauern.
Die Verwendung von Multiplikation ist eine schlechte Idee, da sie anfällig für Überlauf ist.
branchless C-Version:
int sameSign(int a, int b) {
return ~(a^b) & (1<<(sizeof(int)*8-1));
}
C++ Vorlage für Integer-Typen:
template <typename T> T sameSign(T a, T b) {
return ~(a^b) & (1<<(sizeof(T)*8-1));
}
bessere Art und Weise std::signbit wie folgt verwendet:
std::signbit(firstNumber) == std::signbit(secondNumber);
es auch andere Grundtypen unterstützen (double
, float
, char
etc).
- 1. Der einfachste Weg, um Zahlen zu überprüfen
- 2. um zwei oder ohne Vorzeichen ganzen Zahlen
- 3. Gibt es eine einfache Möglichkeit zu überprüfen, ob zwei Zahlen unterschiedliche Zeichen haben?
- 4. Was ist der einfachste Weg in Javascript, um nur das Vorzeichen einer Zahl zu erhalten?
- 5. R-Funktion, um zu prüfen, was falsch ist, wenn zwei Faktorvariablen nicht das gleiche Niveau haben
- 6. Pythonischer Weg, um zu prüfen, ob zwei Wörterbücher den gleichen Schlüsselsatz haben?
- 7. Prüfen, ob benachbarten ganzen Zahlen in der Liste gleich sind
- 8. Guter Weg, ganze Zahlen in C# "anzufügen"?
- 9. Prüfen, ob eine Zeichenfolge Zahlen enthält
- 10. Was ist der einfachste Weg, um sicherzustellen, dass 2 Listen in Lisp die gleiche Länge haben?
- 11. Ganze Zahl ohne Vorzeichen Bitfeld Verschiebung Ausbeuten Ganzzahl mit Vorzeichen
- 12. Wie überprüft man, ob zwei vars die gleiche Referenz haben?
- 13. Der einfachste Weg meinen CLASSPATH zu verwalten?
- 14. Der einfachste Weg, IP-Adresse gegen einen Bereich von Werten zu prüfen mit C#
- 15. lisp -wie zu überprüfen, ob die ganze Liste Zahlen ist
- 16. Der einfachste Weg ein Bild zu zeichnen?
- 17. Was ist der schnellste Weg, um 1 Million ganze Zahlen zu sortieren, wenn ganze Zahlen aus dem Bereich [1.100] kommen?
- 18. Der einfachste Weg, um zu überprüfen, ob das Verfahren durch Castle Dynamicauto implementiert ist
- 19. Java, kombiniert zwei ganze Zahlen zu langen Ergebnissen negative Zahl
- 20. Mapping ganze Zahlen zu dunklen Farben
- 21. Der einfachste Weg, Autoprefixer zu verwenden?
- 22. Was ist der einfachste Weg, eine Koordinatenliste zu erstellen?
- 23. Der einfachste Weg, atomar zu entketten?
- 24. Der einfachste Weg, um Einheit zu lernen
- 25. Der einfachste Weg, Pyg4 zu unterbrechen?
- 26. Ermitteln gerade/ungerade Zahlen (ganze Zahlen)?
- 27. Was ist der einfachste Weg, um SUMPRODUCT
- 28. Prüfen ob das Objekt const
- 29. Wie überprüft man, ob zwei jQuery-Selektoren das gleiche Element ausgewählt haben?
- 30. Prüfen, ob die ganze Zahl mit 0 endet 0
Ganz nett, der C/C++ - Hacker in mir unterstützt dieses Code-Snippet vollständig. Der Softwareingenieur in mir fragt, warum der Benutzer dies in einer generischen Weise wissen muss! – user7116
Schlägt dies nicht fehl, wenn x = 0 und y> 0 ist? –