我想要一个函数,对于负数返回-1,对于正数返回+1.

编辑:具体来说,我正在寻找一个处理浮动的函数.

推荐答案

类型安全的C++版本:

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

好处:

  • 实际上实现了signum(-1、0或1).这里使用copysign的实现只返回-1或1,这不是signum.此外,这里的一些实现返回浮点(或T)而不是int,这似乎是浪费.
  • 适用于int、float、double、unsigned short或任何可从整数0和orderable构造的自定义类型.
  • 快速的copysign是缓慢的,尤其是如果你需要提升,然后再次缩小.这是无分支的,优化效果很好
  • 符合标准!bitshift hack很简单,但只适用于某些位表示,并且在使用未签名类型时不起作用.在适当的情况下,可以将其作为手动专业化提供.
  • 精确的与零进行简单比较可以保持机器内部的高精度表示(例如x87上的80位),并避免过早舍入到零.

注意事项:

  • 这是一个模板,因此在某些情况下可能需要更长的编译时间.

  • 显然,有些人认为使用一个新的、有点深奥、速度非常慢的标准库函数that doesn't even really implement 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>());
     }
    

    (这是第一条警告的一个很好的例子.)

C++相关问答推荐

For循环分段错误

C语言将数字'7'转换为整数7?

HP Nonstop 上的 C:如何获取大于 2GB 的大文件的文件大小?

C2x:将 alignas 作为关键字而不是宏的基本原理是什么?

是否可以在 C 中的 struct 内声明联合?

隐式转换为联合类型?

在 linux 程序中无法使用退格键完全擦除 utf-8 字符

C中是否有unsigned long long int的typedef?

GCC/clang 编译错误,函数作用域静态指针指向未命名数组

如何从 srand(time(0)) 中知道密码

如何编写嵌入式 C 程序以将存储在内存位置的两个数字相加

如何向 lua 文件添加 c 代码函数,反之亦然

C宏中的可变参数格式字符串?

在 C 中使用 printf() 重新实现 printf()

如何通过数组指针访问数组的各个元素?

C - 修改 const struct 内指针的数据

C - 相同的 char[] 变量,不同的输出

如何将指向完整数组的指针(也称为 int(*)[])返回给主函数

使用指针指向c中的某一行

C语言中的怪事:非零不等于一