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

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


当前回答

似乎大多数答案都忽略了最初的问题。

在C/ c++中是否存在标准符号函数(signum, sgn) ?

在标准库中没有,但是有一个copysign可以通过copysign(1.0, arg)以几乎相同的方式使用,在boost中有一个真正的符号函数,它也可能是标准的一部分。

    #include <boost/math/special_functions/sign.hpp>

    //Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
    template <class T>
    inline int sign (const T& z);

其他回答

有一个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/ c++中是否存在标准符号函数(signum, sgn) ?

在标准库中没有,但是有一个copysign可以通过copysign(1.0, arg)以几乎相同的方式使用,在boost中有一个真正的符号函数,它也可能是标准的一部分。

    #include <boost/math/special_functions/sign.hpp>

    //Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
    template <class T>
    inline int sign (const T& z);

我的《C in a Nutshell》揭示了一个叫做copysign的标准函数的存在,它可能很有用。看起来,copyysign(1.0, -2.0)将返回-1.0,而copyysign(1.0, 2.0)将返回+1.0。

很接近吧?

在C/ c++中是否存在标准符号函数(signum, sgn) ?

是的,这取决于定义。

C99及以后版本在<math.h>中有signbit()宏

Int符号位(实浮点x); signbit宏当且仅当其参数值的符号为负时返回一个非零值。C11§7.12.3.6


然而OP想要一些不同的东西。

我想要一个函数,返回-1的负数和+1的正数. ...处理浮点数的函数。

#define signbit_p1_or_n1(x)  ((signbit(x) ?  -1 : 1)

更深层次的问题:

OP的问题在以下情况下不是特定的:x = 0.0, -0.0, +NaN, -NaN。

经典的signum()在x>0时返回+1,在x<0时返回-1,在x==0时返回0。

许多答案已经涵盖了这一点,但没有涉及x = -0.0, +NaN, -NaN。许多都是针对通常缺少Not-a-Numbers (NaN)和-0.0的整数观点。

典型答案函数如signnum_typical()在-0.0,+NaN, -NaN上,它们返回0.0,0.0,0.0。

int signnum_typical(double x) {
  if (x > 0.0) return 1;
  if (x < 0.0) return -1;
  return 0;
}

相反,我建议这样的功能:在-0.0,+NaN, -NaN上,它返回-0.0,+NaN, -NaN。

double signnum_c(double x) {
  if (x > 0.0) return 1.0;
  if (x < 0.0) return -1.0;
  return x;
}

下面重载的接受答案确实不会触发-Wtype-limits。但它确实会触发未使用的参数警告(针对is_signed变量)。为了避免这些,第二个参数不应该这样命名:

template <typename T> inline constexpr
  int signum(T x, std::false_type) {
  return T(0) < x;
}

template <typename T> inline constexpr
  int signum(T x, std::true_type) {
  return (T(0) < x) - (x < T(0));
}

template <typename T> inline constexpr
  int signum(T x) {
  return signum(x, std::is_signed<T>());
}

对于c++ 11或更高版本,可以选择。

template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T const x) {
    return T(0) < x;  
}

template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T const x) {
    return (T(0) < x) - (x < T(0));  
}

对我来说,它不会触发GCC 5.3.1上的任何警告。