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

当它们都是字符时,为什么我不能使用 strcat 组合这两个字符?

最新 container_of 宏中 __mptr 的用途是什么?

HAL_UART_Transmit_IT 如何在 STM32F091VB 上管理串行发送数据

将所有位从最低有效位翻转到最高有效最后 1 位值的最有效方法是什么?

您可以使用 C 内联汇编来对齐指令吗? (没有编译器优化)

如何仅将 C 中 for 循环中的三个最大整数分配给三个单独的变量?

&> 重定向是如何在 UNIX shell 中实现的?

如何使用带有 typedef 的注册存储类?

套接字编程中shutdown()函数中SHUT_RDWR的用途

未定义值的索引处的数组值

使用 -O3 的冒泡排序比使用 GCC 的 -O2 慢

char 数组是否保证为空终止?

绝对值 abs(x) 使用按位运算符和布尔逻辑

从函数返回结构时可能出现 GCC 错误

项目中包含程序集文件时,来自 mmap 的意外 exec 权限

为什么在启用 GCC 优化的情况下,这段代码使用 strlen 的速度要慢 6.5 倍?

C语言中i++和(i)++的区别

gcc中有128位整数吗?

为什么为位字段分配值不返回相同的值?

什么是 C17,语言做了哪些改变?