我想要一个函数为负数返回-1,为正数返回+1。 http://en.wikipedia.org/wiki/Sign_function 我自己编写它很容易,但它似乎应该存在于某个标准库中。

编辑:具体来说,我正在寻找一个函数工作在浮动。


当前回答

有点跑题了,但我用了这个:

template<typename T>
constexpr int sgn(const T &a, const T &b) noexcept{
    return (a > b) - (a < b);
}

template<typename T>
constexpr int sgn(const T &a) noexcept{
    return sgn(a, T(0));
}

我发现第一个函数-有两个参数的函数,比“标准”sgn()更有用,因为它最常在这样的代码中使用:

int comp(unsigned a, unsigned b){
   return sgn( int(a) - int(b) );
}

vs.

int comp(unsigned a, unsigned b){
   return sgn(a, b);
}

无符号类型没有强制转换,也没有额外的减号。

这段代码是用sgn()写的

template <class T>
int comp(const T &a, const T &b){
    log__("all");
    if (a < b)
        return -1;

    if (a > b)
        return +1;

    return 0;
}

inline int comp(int const a, int const b){
    log__("int");
    return a - b;
}

inline int comp(long int const a, long int const b){
    log__("long");
    return sgn(a, b);
}

其他回答

有一种不用分支的方法,但不太好。

sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));

http://graphics.stanford.edu/~seander/bithacks.html

那一页上还有很多其他有趣的、过于聪明的东西……

类型安全的c++版本:

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}

好处:

Actually implements signum (-1, 0, or 1). Implementations here using copysign only return -1 or 1, which is not signum. Also, some implementations here are returning a float (or T) rather than an int, which seems wasteful. Works for ints, floats, doubles, unsigned shorts, or any custom types constructible from integer 0 and orderable. Fast! copysign is slow, especially if you need to promote and then narrow again. This is branchless and optimizes excellently Standards-compliant! The bitshift hack is neat, but only works for some bit representations, and doesn't work when you have an unsigned type. It could be provided as a manual specialization when appropriate. Accurate! Simple comparisons with zero can maintain the machine's internal high-precision representation (e.g. 80 bit on x87), and avoid a premature round to zero.

警告:

It's a template so it might take longer to compile in some circumstances. Apparently some people think use of a new, somewhat esoteric, and very slow standard library function that doesn't even really implement signum is more understandable. The < 0 part of the check triggers GCC's -Wtype-limits warning when instantiated for an unsigned type. You can avoid this by using some overloads: template <typename T> inline constexpr int signum(T x, std::false_type is_signed) { return T(0) < x; } template <typename T> inline constexpr int signum(T x, std::true_type is_signed) { return (T(0) < x) - (x < T(0)); } template <typename T> inline constexpr int signum(T x) { return signum(x, std::is_signed<T>()); } (Which is a good example of the first caveat.)

有一个C99数学库函数叫copysign(),它从一个参数取符号,从另一个参数取绝对值:

result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double

会给你一个+/- 1.0的结果,这取决于值的符号。注意,浮点零是有符号的:(+0)将产生+1,(-0)将产生-1。

显然,最初的帖子的问题的答案是否定的。没有标准的c++ sgn函数。

为什么使用三元操作符和if-else,当你可以简单地这样做

#define sgn(x) x==0 ? 0 : x/abs(x)