C++ 浮点数的符号

C++ 浮点数的符号,c++,floating-point,signedness,C++,Floating Point,Signedness,有没有一种简单的方法来确定浮点数的符号 我进行了试验,得出了以下结论: #include <iostream> int main(int argc, char** argv) { union { float f; char c[4]; }; f = -0.0f; std::cout << (c[3] & 0x10000000) << "\n"; std::cin.ignore(); std::cin.get(); retu

有没有一种简单的方法来确定浮点数的符号

我进行了试验,得出了以下结论:

#include <iostream>

int main(int argc, char** argv)
{
 union
 {
  float f;
  char c[4];
 };

 f = -0.0f;
 std::cout << (c[3] & 0x10000000) << "\n";

 std::cin.ignore();
 std::cin.get();
 return 0;
}
#包括
int main(int argc,字符**argv)
{
联盟
{
浮动f;
charc[4];
};
f=-0.0f;

std::cout假设它是一个有效的浮点数(而不是NaN):

float f;
bool为负=f<0;
读者可以通过练习了解如何测试浮点数是否为正数。

使用math.h中的signbit()。

如果(f<0.0)
?,为什么不试试

float s = copysign(1, f);

另一个有用的东西可能是#包括
,如果它在您的系统/编译器上可用。

1)sizeof(int)与此无关

2) 假设CHAR_位==8,是的

3) 为此我们需要MSB,但endianness只影响字节顺序,而不影响位顺序,因此我们需要检查的位是
c[0]&0x80
,对于大endianness,或者
c[3]&0x80
,但影响很小,因此最好用
uint32\u t
声明并集,并用0x8000000进行检查


此技巧仅适用于非特殊内存操作数。对XMM或x87寄存器中的
浮点值执行此操作将比直接方法慢。此外,它不会像NaN或INF那样处理特殊值。

谷歌搜索系统的浮点格式。许多操作使用IEEE 754,并且在要处理的数据中有特定的符号位检查.1为负数,0为正数。其他格式也有类似的内容,并且同样易于检查

注意:试图通过硬编码赋值(如f=-0.0F;)让编译器准确地给出所需的数字可能不起作用。与浮点格式无关,但与解析器和编译器使用的C/C++库有关。生成负零通常可能很简单,也可能不那么简单。

我有这个问题嗯 试试这个:

/* IEEE floating-point number's bits:  sign  exponent   mantissa */
struct float_bits {
    unsigned int fraction:23; /**< Value is binary 1.fraction ("mantissa") */
    unsigned int exp:8; /**< Value is 2^(exp-127) */
    unsigned int sign:1; /**< 0 for positive, 1 for negative */
};

/* A union is a struct where all the fields *overlap* each other */
union float_dissector {
    float f;
    struct float_bits b;
};

int main() {
    union float_dissector s;
    s.f = 16;
    printf("float %f  sign %u  exp %d  fraction %u",s.f, s.b.sign,((int)s.b.exp - 127),s.b.fraction);
    return 0;
}
/*IEEE浮点数位:符号指数尾数*/
结构浮点数{
无符号整数分数:23;/**<值为二进制1.0分数(“尾数”)*/
无符号整数exp:8;/**<值为2^(exp-127)*/
无符号整数符号:1;/**<0表示正,1表示负*/
};
/*并集是所有字段*相互重叠*的结构*/
联合浮球解剖器{
浮动f;
结构浮点_位b;
};
int main(){
联合漂浮解剖器;
s、 f=16;
printf(“浮点%f符号%u exp%d分数%u”、s.f、s.b.sign、((int)s.b.exp-127)、s.b.fraction);
返回0;
}

来得这么晚,但我想到了另一种方法

如果您知道系统使用IEEE754浮点格式,但不知道浮点类型相对于整数类型有多大,则可以执行以下操作:

bool isFloatIEEE754Negative(float f)
{
    float d = f;
    if (sizeof(float)==sizeof(unsigned short int)) {
        return (*(unsigned short int *)(&d) >> (sizeof(unsigned short int)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned int)) {
        return (*(unsigned int *)(&d) >> (sizeof(unsigned int)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned long)) {
        return (*(unsigned long *)(&d) >> (sizeof(unsigned long)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned char)) {
        return (*(unsigned char *)(&d) >> (sizeof(unsigned char)*CHAR_BIT - 1) == 1);
    }
    else if (sizeof(float)==sizeof(unsigned long long)) {
        return (*(unsigned long long *)(&d) >> (sizeof(unsigned long long)*CHAR_BIT - 1) == 1);
    }
    return false; // Should never get here if you've covered all the potential types!
}
本质上,您将浮点中的字节视为无符号整数类型,然后右移除一个位(符号位)之外的所有位。'>>'在不考虑endianness的情况下工作,因此可以绕过该问题

如果可以确定执行前哪个无符号整数类型的长度与浮点类型的长度相同,则可以缩写为:

#define FLOAT_EQUIV_AS_UINT unsigned int // or whatever it is

bool isFloatIEEE754Negative(float f)
{
    float d = f;
    return (*(FLOAT_EQUIV_AS_UINT *)(&d) >> (sizeof(FLOAT_EQUIV_AS_UINT)*CHAR_BIT - 1) == 1);
}
这在我的测试系统上起了作用;有人看到任何警告或被忽略的“陷阱”吗?

(int)(x>0)-(int)(x<0);
(int)(x > 0) - (int)(x < 0);

在我们知道您使用的是哪种系统之前,我们如何纠正您关于您的机器是大端还是小端的假设?我的假设是泛化的,如果不清楚的话,很抱歉。@hhafez有什么问题,因为我得到的唯一结果是-0和+0。这是不可能的,因为-0.0f==0.0fB,因为浮点数有两个零-0.0f和+0。0f@Rarge:我附和@GMan对@James McNellis的回答的评论。这并没有提供问题的答案。若要评论或要求作者澄清,请在其帖子下方留下评论。-@Will-这与公认答案的关键基本相同,因此我认为它确实回答了问题(虽然这是6年前的事了,但已经有一段时间了。)这与“批评”或“澄清”有什么关系?自动生成的注释放错了位置?这是审阅队列中的选项之一--这更像是一个注释而不是一个完整的答案。但是,是的,请忽略它。接受的答案解释得更好。简短的一行答案也可能是注释。@Rarge:你在做什么?这很重要?@Rarge:如果你依赖于能够点积计算后,
+0
-0
之间有什么区别?公平地说,你的算法非常不稳定吗?@Rarge:垂直点积给出0的唯一情况是两个向量平行(考虑到浮点数学的局限性,几乎无法区分)。在这种情况下,期望
+0
-0
之间的差异有意义是不合理的。威廉·卡汉的论文包括一些引人注目的例子(如流体力学)这说明了为什么区分+0.0和-0.0很重要。简言之,这与复杂函数、分支切割和身份有关,除非区分+0.0和-0.0,否则这些身份无法成立。@Jim:深奥的意思是(这并不是要淡化它们)用例是两个向量的点积不是这些情况之一。<代码>符号()>代码>不是当前C++标准库的一部分。它是提议的C++ 0x标准库的一部分(C99标准库的大部分-全部)是C++ + 0x的一部分。@ JAMESMCNELIS现在在C++ 11,<代码>不是当前C++标准库的一部分。它是提议的C++ 0x标准库的一部分(C99标准库中的大部分——全部是C++ 0x的一部分)。@弗拉德:这只是把GoalPoST从“它绝对可用”到“它可能是可用的”。请坚持原来的论点,即“杰姆斯提出”,这是“这不是标准”,你没有反驳。诚实点,接受它,然后行动
(int)(x > 0) - (int)(x < 0);