类型安全的 C++ 版本:
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
好处:
- 实际上实现了符号(-1、0 或 1)。此处使用 copysign 的实现仅返回 -1 或 1,这不是符号。此外,这里的一些实现返回一个 float (或 T)而不是一个 int,这似乎很浪费。
- 适用于整数、 float 、 double 、无符号短裤或任何可从整数 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>());
}
(这是第一个警告的一个很好的例子。)
我是一名优秀的程序员,十分优秀!