Gegeben zwei Gleitkommazahlen, ich suche nach einer effizienten Möglichkeit zu überprüfen, ob sie das gleiche Vorzeichen haben, gegeben, falls vorhanden der beiden Werte ist Null (+0,0 oder -0,0), sie sollten als gleiches Vorzeichen betrachtet werden.Wie man das Vorzeichen zweier Gleitkommawerte bei der Behandlung negativer Nullen effizient vergleicht
Zum Beispiel
- SameSign (1.0, 2.0) sollte return true
- SameSign (-1.0, -2.0) sollten wahre
- SameSign (-1.0, 2.0) zurückgeben sollte return false
- SameSign (0.0, 1.0) sollte return true
- SameSign (0.0, -1.0) sollte true zurück
- SameSign (-0.0, 1.0) sollte return true
- SameSign (-0.0, -1.0) sollten
A naive aber korrekte Umsetzung der SameSign
in C++ true zurück wäre:
bool SameSign(float a, float b)
{
if (fabs(a) == 0.0f || fabs(b) == 0.0f)
return true;
return (a >= 0.0f) == (b >= 0.0f);
}
die IEEE Unter der Annahme Gleitkommazahlen Modell, hier ist eine Variante von SameSign
, die (zumindest mit Visual C++ 2008) branchless Code kompiliert:
bool SameSign(float a, float b)
{
int ia = binary_cast<int>(a);
int ib = binary_cast<int>(b);
int az = (ia & 0x7FFFFFFF) == 0;
int bz = (ib & 0x7FFFFFFF) == 0;
int ab = (ia^ib) >= 0;
return (az | bz | ab) != 0;
}
mit binary_cast
wie folgt definiert:
template <typename Target, typename Source>
inline Target binary_cast(Source s)
{
union
{
Source m_source;
Target m_target;
} u;
u.m_source = s;
return u.m_target;
}
Ich suche nach zwei Dinge:
Eine schnellere, effizientere Implementierung von
SameSign
, mit Bit-Tricks, FPU Tricks oder sogar SSE-Intrinsics.Eine effiziente Erweiterung von
SameSign
zu drei Werten.
Edit:
ich einige Performance-Messungen an den drei Varianten von SameSign
gemacht haben (die beiden Varianten in der ursprünglichen Frage beschrieben, sowie Stephen eins). Jede Funktion wurde 200-400 Mal auf allen aufeinanderfolgenden Wertepaaren in einem Array von 101 zufällig mit -1,0, -0,0, +0,0 und +1,0 aufgefüllten Schwimmern ausgeführt. Jede Messung wurde 2000 mal wiederholt und die Mindestzeit wurde eingehalten (um alle Cache-Effekte und systembedingten Verlangsamungen auszumerzen). Der Code wurde mit Visual C++ 2008 SP1 mit maximaler Optimierung und aktivierter SSE2-Codegenerierung kompiliert. Die Messungen wurden mit einem Core 2 Duo P8600 2,4 Ghz durchgeführt.
Hier werden die Zeitpunkte sind, nicht den Overhead des Abrufens Eingangswerte aus dem Array zu zählen, die Funktion aufrufen und das Ergebnis (in Höhe von 6-7 clockticks) Abrufen:
- Naive Variante: 15 ticks
- Bit magische Variante: 13 ticks
- Stephens Variante: 6 ticks
Jede bestimmte Sprache/Plattform? –
Hey, danke für die gute Frage :) Vorzugsweise C/C++ auf x86. –
mögliches Duplikat von [vergleicht zwei Floats, um zu sehen, ob sie beide negativ oder beide positiv sind.] (Http://stackoverflow.com/questions/2013680/comparting-two-floats-to-see-if-theyre-both Negativ oder positiv positiv – ChrisF