Dado dos números de punto flotante, estoy buscando un eficiente forma de comprobar si tienen el mismo signo, dado que, de haberlo, de los dos valores es cero (+0.0 o -0.0), se debe considerar que tienen el mismo signo.Cómo comparar eficientemente el signo de dos valores de punto flotante mientras se manejan ceros negativos
Por ejemplo,
- SameSign (1.0, 2.0) debe devolver verdadero
- SameSign (-1,0, -2,0) debe devolver verdadero
- SameSign (-1,0, 2,0) debe devolver falsa
- SameSign (0.0, 1.0) debería devolver cierto
- SameSign (0,0, -1,0) debe devolver verdadero
- SameSign (-0,0, 1,0) debería devolver cierto
- SameSign (-0,0, -1,0) debe devolver verdadero
Una implementación ingenua pero correcta de SameSign
en C++ sería:
bool SameSign(float a, float b)
{
if (fabs(a) == 0.0f || fabs(b) == 0.0f)
return true;
return (a >= 0.0f) == (b >= 0.0f);
}
Suponiendo que el modelo de punto flotante IEEE, he aquí una variante de SameSign
que compila a código sin sucursales (al menos con 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;
}
con binary_cast
define de la siguiente manera:
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;
}
Busco dos cosas:
una implementación más rápida, más eficiente de
SameSign
, usando trucos bits, FPU trucos o incluso intrínseca SSE.Una extensión eficiente de
SameSign
a tres valores.
Editar:
He hecho algunas mediciones de rendimiento en las tres variantes de SameSign
(las dos variantes descritas en la pregunta original, además de Stephen uno). Cada función se ejecutó de 200 a 400 veces, en todos los pares consecutivos de valores en una matriz de 101 flotantes llenos al azar con -1.0, -0.0, +0.0 y +1.0. Cada medición se repitió 2000 veces y se mantuvo el tiempo mínimo (para descartar todos los efectos de caché y las ralentizaciones inducidas por el sistema). El código se compiló con Visual C++ 2008 SP1 con la optimización máxima y la generación de código SSE2 habilitada. Las mediciones se realizaron en un Core 2 Duo P8600 2.4 Ghz.
Aquí son los tiempos, sin contar la sobrecarga de ir a buscar valores de entrada de la matriz, llamando a la función y recuperar el resultado (que ascienden a 6-7 clockticks):
- variante Naive: 15 garrapatas
- Bit variante de la magia: 13 garrapatas
- variante de Stephens: 6 garrapatas
Cualquier lenguaje/plataforma en particular? –
Oye, gracias por la buena pregunta :) Preferiblemente C/C++ en x86. –
posible duplicado de [comparación de dos flotantes para ver si ambos son negativos, o ambos positivos.] (Http://stackoverflow.com/questions/2013680/comparing-two-floats-to-see-if-theyre-both -negativo-o-ambos-positivo) – ChrisF