C/C++ 中是否有标准的符号函数(signum、sgn)? [英] Is there a standard sign function (signum, sgn) in C/C++?

查看:29
本文介绍了C/C++ 中是否有标准的符号函数(signum、sgn)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want a function that returns -1 for negative numbers and +1 for positive numbers. http://en.wikipedia.org/wiki/Sign_function It's easy enough to write my own, but it seems like something that ought to be in a standard library somewhere.

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

Specifically, I was looking for a function working on floats.

推荐答案

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

Surprised no one has posted the type-safe C++ version yet:

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

优点:

  • 实际上实现了符号(-1、0 或 1).此处使用 copysign 的实现仅返回 -1 或 1,这不是 signum.此外,这里的一些实现返回的是浮点数(或 T)而不是整数,这似乎很浪费.
  • 适用于整数、浮点数、双精度数、无符号短整数或任何可从整数 0 构造且可排序的自定义类型.
  • 快!copysign 很慢,特别是如果你需要推广然后再次缩小.这是无分支的并且优化得很好
  • 符合标准!bitshift hack 很简洁,但仅适用于某些位表示,并且在您拥有无符号类型时不起作用.在适当的时候,它可以作为手动专业化提供.
  • 准确!与零的简单比较可以保持机器内部的高精度表示(例如 x87 上的 80 位),并避免过早舍入到零.
  • Actually implements signum (-1, 0, or 1). Implementations here using copysign only return -1 or 1, which is not signum. Also, some implementations here are returning a float (or T) rather than an int, which seems wasteful.
  • Works for ints, floats, doubles, unsigned shorts, or any custom types constructible from integer 0 and orderable.
  • Fast! copysign is slow, especially if you need to promote and then narrow again. This is branchless and optimizes excellently
  • Standards-compliant! The bitshift hack is neat, but only works for some bit representations, and doesn't work when you have an unsigned type. It could be provided as a manual specialization when appropriate.
  • Accurate! Simple comparisons with zero can maintain the machine's internal high-precision representation (e.g. 80 bit on x87), and avoid a premature round to zero.

注意事项:

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

  • It's a template so it might take longer to compile in some circumstances.
  • Apparently some people think use of a new, somewhat esoteric, and very slow standard library function that doesn't even really implement signum is more understandable.
  • The < 0 part of the check triggers GCC's -Wtype-limits warning when instantiated for an unsigned type. You can avoid this by using some overloads:

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>());
}

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

(Which is a good example of the first caveat.)

这篇关于C/C++ 中是否有标准的符号函数(signum、sgn)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆