How to efficiently compare the sign of two floating-point values while handling negative zeros

南楼画角 提交于 2019-11-30 12:56:57

If you don't need to support infinities, you can just use:

inline bool SameSign(float a, float b) {
    return a*b >= 0.0f;
}

which is actually pretty fast on most modern hardware, and is completely portable. It doesn't work properly in the (zero, infinity) case however, because zero * infinity is NaN, and the comparison will return false, regardless of the signs. It will also incur a denormal stall on some hardware when a and b are both tiny.

perhaps something like:

inline bool same_sign(float a, float b) {
    return copysignf(a,b) == a;
}

see the man page for copysign for more info on what it does (also you may want to check that -0 != +0)

or possibly this if you have C99 functions

inline bool same_sign(float a, float b) {
    return signbitf(a) == signbitf(b);
}

as a side note, on gcc at least both copysign and signbit are builtin functions so they should be fast, if you want to make sure the builtin version is being used you can do __builtin_signbitf(a)

EDIT: this should also be easy to extend to the 3 value case as well (actually both of these should...)

inline bool same_sign(float a, float b, float c) {
    return copysignf(a,b) == a && copysignf(a,c) == a;
}

// trust the compiler to do common sub-expression elimination
inline bool same_sign(float a, float b, float c) {
    return signbitf(a) == signbitf(b) && signbitf(a) == signbitf(c);
}

// the manpages do not say that signbit returns 1 for negative... however
// if it does this should be good, (no branches for one thing...)
inline bool same_sign(float a, float b, float c) {
    int s = signbitf(a) + signbitf(b) + signbitf(c);
    return !s || s==3;
}

A small note on signbit: The macro returns an int and the man page states that "It returns a nonzero value if the value of x has its sign bit set." This means that the Spudd86's bool same_sign() is not guaranteed to work in case signbit returns two different non-zero int's for two different negative values.

Casting to bool first ensures a correct return value:

inline bool same_sign(float a, float b) {
    return (bool)signbitf(a) == (bool)signbitf(b);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!