问题描述
我想要一个函数,它为负数返回 -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)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!