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

编辑:具体来说,我正在寻找对浮点数起作用的函数。

最佳答案

惊讶的是没有人发布过类型安全的C++版本:

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

好处:
  • 实际上实现了signum(-1、0或1)。此处使用copysign的实现仅返回-1或1,而不是signum。另外,这里的某些实现返回的是float(或T)而不是int,这似乎很浪费。
  • 适用于int,float,double,unsigned short或任何可从整数0构造且可排序的自定义类型。
  • 快! copysign速度很慢,特别是如果您需要提升然后再次缩小范围时。这是无分支的,并且优化了
  • 符合标准! bitshift hack很简洁,但仅适用于某些位表示形式,当您使用unsigned类型时不起作用。适当时,可以将其作为手动专业提供。
  • 准确!简单的零比较可以保持机器内部的高精度表示(例如x87上的80位),并避免过早舍入为零。

  • 注意事项:
  • 这是一个模板,因此在某些情况下可能需要更长的时间进行编译。
  • 显然,有些人认为使用新的,有些深奥的,非常慢的标准库函数(甚至没有真正实现signum)更容易理解。
  • 当实例化为无符号类型时,检查的< 0部分会触发GCC的-Wtype-limits警告。您可以通过使用一些重载来避免这种情况:
    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>());
    }
    

    (这是第一个警告的好例子。)
  • 10-08 00:40