我想要一个函数,对于负数返回-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++相关问答推荐

在#include中使用C宏变量

编译的时候g++通常会比GCC慢很多吗?

GCC预处理宏和#杂注GCC展开

为什么在函数内部分配内存空间时需要添加符号?

为什么内核使用扩展到前后相同的宏定义?

Vcpkg的配置文件

如何将另一个数组添加到集合中,特别是字符串?

在C++中父进程和子进程中的TAILQ队列同步问题

处理EPOLL_WAIT中的接收数据和连接关闭信号

C11/C17标准允许编译器清除复合文字内存吗?

将回调/基于事件的C API转换为非回调API

递归打印二维数组(C编程)

为什么二进制文件的大小不会随着静态数据的大小而增加?

将char*数组深度复制到 struct 中?

如何不断地用C读取文件?

macos/arm64 上地址空间不使用第一位吗?

返回指向函数内声明的复合文字的指针是否安全,还是应该使用 malloc?

无法在 C 中打开文本文件,我想从中读取文本作为数据并将其写入数组

为什么这里的符号没有解析?

为什么CMake构建的程序比命令构建的程序运行得慢