我想要一个函数为负数返回-1,为正数返回+1。 http://en.wikipedia.org/wiki/Sign_function 我自己编写它很容易,但它似乎应该存在于某个标准库中。
编辑:具体来说,我正在寻找一个函数工作在浮动。
我想要一个函数为负数返回-1,为正数返回+1。 http://en.wikipedia.org/wiki/Sign_function 我自己编写它很容易,但它似乎应该存在于某个标准库中。
编辑:具体来说,我正在寻找一个函数工作在浮动。
当前回答
这是一个分支友好的实现:
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
除非你的数据有一半是0,否则分支预测器会选择一个最常见的分支。两个分支都只涉及简单的操作。
另外,在一些编译器和CPU架构上,完全无分支的版本可能更快:
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
这适用于IEEE 754双精度二进制浮点格式:binary64。
其他回答
我的《C in a Nutshell》揭示了一个叫做copysign的标准函数的存在,它可能很有用。看起来,copyysign(1.0, -2.0)将返回-1.0,而copyysign(1.0, 2.0)将返回+1.0。
很接近吧?
我不知道它的标准函数。这里有一种有趣的写法:
(x > 0) - (x < 0)
这里有一个更容易理解的方法:
if (x > 0) return 1;
if (x < 0) return -1;
return 0;
如果你喜欢三元运算符,你可以这样做:
(x > 0) ? 1 : ((x < 0) ? -1 : 0)
有一种不用分支的方法,但不太好。
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
http://graphics.stanford.edu/~seander/bithacks.html
那一页上还有很多其他有趣的、过于聪明的东西……
这是一个分支友好的实现:
inline int signum(const double x) {
if(x == 0) return 0;
return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
除非你的数据有一半是0,否则分支预测器会选择一个最常见的分支。两个分支都只涉及简单的操作。
另外,在一些编译器和CPU架构上,完全无分支的版本可能更快:
inline int signum(const double x) {
return (x != 0) *
(1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
这适用于IEEE 754双精度二进制浮点格式:binary64。
double signof(double a) { return (a == 0) ? 0 : (a<0 ? -1 : 1); }