Szukam dwóch liczb zmiennoprzecinkowych, szukam sposobu wydajnego, aby sprawdzić, czy mają ten sam znak, biorąc pod uwagę, że jeśli jakieś z dwóch wartości wynosi zero (+0,0 lub -0,0), należy uznać, że mają ten sam znak.Jak skutecznie porównywać znak dwóch wartości zmiennoprzecinkowych podczas obsługi zer ujemnych
Przykładowo
- SameSign (1,0, 2,0) powinien wrócić prawdziwego
- SameSign (-1.0, 2,0) powinien wrócić prawdziwego
- SameSign (-1.0 2,0) powinien zwraca fałsz
- SameSign (0,0, 1,0), należy zwrócić prawdziwego
- SameSign (0,0, -1,0), należy zwrócić prawda
- SameSign (-0,0, 1,0) powinien wrócić prawdziwego
- SameSign (-0.0, -1,0), należy zwrócić prawda
naiwny jednak właściwe stosowanie SameSign
C++ może być:
bool SameSign(float a, float b)
{
if (fabs(a) == 0.0f || fabs(b) == 0.0f)
return true;
return (a >= 0.0f) == (b >= 0.0f);
}
Zakładając zmiennoprzecinkowej IEEE modelu, oto wariant SameSign
który kompiluje się do kodu branchless (przynajmniej z Visual C++ 2008):
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;
}
z binary_cast
zdefiniowane następująco:
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;
}
Szukam dwóch rzeczy:
Szybsza, bardziej efektywne wdrożenie
SameSign
, wiertłem sztuczek, FPU sztuczki, a nawet wewnętrzne SSE.Skuteczne rozszerzenie
SameSign
na trzy wartości.
Edit:
Zrobiłem kilka pomiarów wydajności na trzech wariantów SameSign
(dwóch wariantów opisanych w oryginalne pytanie, plus Stephen jeden). Każda funkcja była uruchamiana 200-400 razy, na wszystkich kolejnych parach wartości w tablicy 101 płynów wypełnionych losowo z -1,0, -0,0, +0,0 i +1,0. Każdy pomiar powtórzono 2000 razy i utrzymano minimalny czas (aby wyeliminować wszystkie efekty pamięci podręcznej i spowolnienia wywołane przez system). Kod został skompilowany z Visual C++ 2008 SP1 z maksymalną optymalizacją i włączonym generowaniem kodu SSE2. Pomiary przeprowadzono na Core 2 Duo P8600 2,4 Ghz.
Oto czasy nie licząc napowietrznej pobierania wartości wejściowych z tablicy wywoływania odzyskiwania funkcji i wynik (które wynoszą 6-7 clockticks):
- wariant Naiwne 15 kleszczy
- Bit magia wariant: 13 kleszczy
- Stephens za wariant: 6 kleszcze
jakiś szczególny język/platformy? –
Hej, dzięki za dobre pytanie :) Najlepiej C/C++ na x86. –
możliwy duplikat [porównywania dwóch elementów pływających, aby sprawdzić, czy oba są ujemne, czy oba są dodatnie.] (Http://stackoverflow.com/questions/2013680/porównanie-dwa-przypadków-do-widoczenia-wysokie-obszary -negative-or-both-positive) – ChrisF