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

C++ C/C+中是否有标准符号函数(signum,sgn)+;?,c++,c,math,C++,C,Math,我想要一个函数,对于负数返回-1,对于正数返回+1。 写我自己的很容易,但它似乎应该放在某个地方的标准库中 编辑:具体地说,我正在寻找一个处理浮动的函数。我不知道它的标准函数。下面是一个有趣的写作方法: (x > 0) - (x < 0) (x>0)-(x0)返回1; 如果(x0)?1:((x显然,原始海报问题的答案是“否”。没有标准的C++ +代码> SGN < /代码>函数。< /P>代码>双符号(double a){返回(A==0)0:(a<P>),似乎大多数答案都没有回答原

我想要一个函数,对于负数返回-1,对于正数返回+1。 写我自己的很容易,但它似乎应该放在某个地方的标准库中


编辑:具体地说,我正在寻找一个处理浮动的函数。

我不知道它的标准函数。下面是一个有趣的写作方法:

(x > 0) - (x < 0)
(x>0)-(x<0)
以下是一种更具可读性的方法:

if (x > 0) return 1;
if (x < 0) return -1;
return 0;
if(x>0)返回1;
如果(x<0)返回-1;
返回0;
如果您喜欢三元运算符,可以执行以下操作:

(x > 0) ? 1 : ((x < 0) ? -1 : 0)
(x>0)?1:((x<0)?-1:0)

有一种不用分支的方法,但它不是很漂亮

sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));


该页面上还有许多其他有趣的、过于聪明的东西……

简而言之,我的C副本揭示了一个名为copysign的标准函数的存在,它可能很有用。看起来copysign(1.0,-2.0)将返回-1.0,copysign(1.0,2.0)将返回+1.0


非常接近,是吧?

有一个C99数学库函数,名为copysign(),它从一个参数获取符号,从另一个参数获取绝对值:

result = copysign(1.0, value) // double
result = copysignf(1.0, value) // float
result = copysignl(1.0, value) // long double

将根据值的符号给出+/-1.0的结果。请注意,浮点零是有符号的:(+0)将产生+1,(-0)将产生-1。

如果您只想测试符号,请使用(如果其参数有负号,则返回true)。 不确定您为什么特别希望返回-1或+1;文案更方便 对于这一点,但在一些具有
只对负零点进行部分支持,其中符号位可能返回true。

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

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}
(这是第一条警告的一个很好的例子。)


比上述解决方案更快,包括最高评级的解决方案:

(x < 0) ? -1 : (x > 0)
(x<0)-1:(x>0)
整数符号(浮点数n)
{     
联合{float f;std::uint32_t i;}u{n};

返回1 -((Ui>31))P>显然,原始海报问题的答案是“否”。没有标准的C++ +代码> SGN < /代码>函数。< /P>代码>双符号(double a){返回(A==0)0:(a<P>),似乎大多数答案都没有回答原始问题。

double signof(double a) { return (a == 0) ? 0 : (a<0 ? -1 : 1); }
C/C++中是否有标准的符号函数(signum,sgn)

不在标准库中,但是有一个可以通过
copysign(1.0,arg)
以几乎相同的方式使用的函数,并且在中有一个true sign函数,它可能是标准的一部分

    #include <boost/math/special_functions/sign.hpp>

    //Returns 1 if x > 0, -1 if x < 0, and 0 if x is zero.
    template <class T>
    inline int sign (const T& z);
#包括
//如果x>0,则返回1;如果x<0,则返回1;如果x为零,则返回0。
模板
内联整数符号(常数T&z);

< /P> < P>不,它不存在于C++中,就像在Matlab中一样。我在程序中使用宏来实现这个。

#define sign(a) ( ( (a) < 0 )  ?  -1   : ( (a) > 0 ) )
定义符号(a)((a)<0)?-1:((a)>0))
一般来说,C/C++中没有标准的signum函数,缺少这样一个基本函数可以告诉您很多关于这些语言的信息

除此之外,我相信大多数人关于定义这样一个函数的正确方法的观点在某种程度上是正确的,如果你考虑到两个重要的警告,关于它的“争议”实际上是没有争议的:

  • signum函数应始终返回其操作数的类型,类似于
    abs()
    函数,因为signum通常在绝对值经过某种处理后用于与绝对值相乘。因此,signum的主要使用情况不是比较,而是算术,后者不应涉及任何昂贵的整数到浮点的转换

  • 浮点类型没有一个精确的零值:+0.0可以解释为“零上无穷小”,而-0.0可以解释为“零下无穷小”。这就是为什么涉及零的比较必须在内部检查这两个值,而像
    x==0.0
    这样的表达式可能是危险的

关于C,我认为使用整数类型的最好方法确实是使用
(x>0)-(x<0)
表达式,因为它应该以无分支的方式进行翻译,并且只需要三个基本操作。最好定义强制返回类型与参数类型匹配的内联函数,并添加C11
define\u Generic
以将这些函数映射到公共名称

对于浮点值,我认为基于C11
copysignf(1.0f,x)
copysign(1.0,x)
copysignl(1.0l,x)的内联函数
是一个不错的选择,因为它们也很可能是无分支的,而且不需要将整数的结果转换回浮点值。您可能应该特别指出,由于浮点零的特性,您的signum浮点实现不会返回零值、处理时间的考虑因素,还因为在浮点运算中接收正确的-1/+1符号通常非常有用,即使对于零值也是如此

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

是的,取决于定义

C99及更高版本在

int-signbit
(实浮点
x
);
signbit
宏当且仅当其参数值的符号为负值时返回非零值。C11§7.12.3.6


然而,OP想要一些不同的东西

我想要一个函数,对于负数返回-1,对于正数返回+1……一个处理浮点数的函数


更深:

在以下情况下,post不是特定的:
x=0.0,-0.0,+NaN,-NaN

double signnum_c(double x) {
  if (x > 0.0) return 1.0;
  if (x < 0.0) return -1.0;
  return x;
}

经典型在
x>0
上返回
+1
x上返回
-1
,下面重载的接受答案确实不会触发-Wtype-l
#define sign(a) ( ( (a) < 0 )  ?  -1   : ( (a) > 0 ) )
#define signbit_p1_or_n1(x)  ((signbit(x) ?  -1 : 1)
int signnum_typical(double x) {
  if (x > 0.0) return 1;
  if (x < 0.0) return -1;
  return 0;
}
double signnum_c(double x) {
  if (x > 0.0) return 1.0;
  if (x < 0.0) return -1.0;
  return x;
}
template <typename T> inline constexpr
  int signum(T x, std::false_type) {
  return T(0) < x;
}

template <typename T> inline constexpr
  int signum(T x, std::true_type) {
  return (T(0) < x) - (x < T(0));
}

template <typename T> inline constexpr
  int signum(T x) {
  return signum(x, std::is_signed<T>());
}
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, int>::type
inline constexpr signum(T const x) {
    return T(0) < x;  
}

template <typename T>
typename std::enable_if<std::is_signed<T>::value, int>::type
inline constexpr signum(T const x) {
    return (T(0) < x) - (x < T(0));  
}
template<typename T>
constexpr int sgn(const T &a, const T &b) noexcept{
    return (a > b) - (a < b);
}

template<typename T>
constexpr int sgn(const T &a) noexcept{
    return sgn(a, T(0));
}
int comp(unsigned a, unsigned b){
   return sgn( int(a) - int(b) );
}
int comp(unsigned a, unsigned b){
   return sgn(a, b);
}
template <class T>
int comp(const T &a, const T &b){
    log__("all");
    if (a < b)
        return -1;

    if (a > b)
        return +1;

    return 0;
}

inline int comp(int const a, int const b){
    log__("int");
    return a - b;
}

inline int comp(long int const a, long int const b){
    log__("long");
    return sgn(a, b);
}
template <typename T> double sgn(T val) {
    return double((T(0) < val) - (val < T(0)))/(val == val);
}
#define sgn(x) x==0 ? 0 : x/abs(x)
inline int signum(const double x) {
    if(x == 0) return 0;
    return (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}
inline int signum(const double x) {
    return (x != 0) * 
        (1 - (static_cast<int>((*reinterpret_cast<const uint64_t*>(&x)) >> 63) << 1));
}