C/C 中是否有标准符号函数(signum,sgn)?

新手上路,请多包涵

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

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

原文由 batty 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

类型安全的 C++ 版本:

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

好处:

  • 实际上实现了符号(-1、0 或 1)。此处使用 copysign 的实现仅返回 -1 或 1,这不是符号。此外,这里的一些实现返回一个浮点数(或 T)而不是一个 int,这似乎很浪费。
  • 适用于整数、浮点数、双精度数、无符号短裤或任何可从整数 0 构造且可排序的自定义类型。
  • 快速地! copysign 很慢,尤其是当您需要提升然后再次缩小时。这是无分支的,并且优化得很好
  • 符合标准! bitshift hack 很简洁,但仅适用于某些位表示,并且在您具有无符号类型时不起作用。在适当的时候,它可以作为手动专业化提供。
  • 准确的!与零的简单比较可以保持机器内部的高精度表示(例如 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>());
   }

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

原文由 user79758 发布,翻译遵循 CC BY-SA 4.0 许可协议

这个问题很老,但现在有这种所需的功能。我添加了一个带有 not、left shift 和 dec 的包装器。

您可以使用基于 C99 中符号位的包装函数来获得所需的确切行为(请参阅下面的代码)。

返回 x 的符号是否为负。

这也可以应用于无穷大、NaN 和零(如果零是无符号的,则认为它是正数)

 #include <math.h>

int signValue(float a) {
    return ((!signbit(a)) << 1) - 1;
}

注意:我使用操作数而不是(“!”),因为符号位的返回值未指定为 1(即使示例让我们认为它总是这样)但对于负数是正确的:

返回值

如果 x 的符号为负,则为非零值(真);否则为零(假)。

然后我用左移乘以 2(“<< 1”),这将给我们 2 表示正数和 0 表示负数,最后减 1 以获得 1 和 -1 分别表示所要求的正数和负数操作。

原文由 Antonin GAVREL 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题