简体   繁体   English

浮点数的符号

[英]Sign of a floating point number

Is there an easy way to determine the sign of a floating point number?有没有一种简单的方法来确定浮点数的符号?

I experimented and came up with this:我进行了实验并提出了这个:

#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;
}

where (c[3] & 0x10000000) gives a value > 0 for a negative number but I think this requires me to make the assumptions that:其中 (c[3] & 0x10000000) 给出一个值 > 0 表示负数,但我认为这需要我做出以下假设:

  • The machine's bytes are 8 bits big机器的字节是 8 位大
  • a float point number is 4 bytes big?浮点数有 4 个字节大吗?
  • the machine's most significant bit is the left-most bit (endianness?)机器的最高有效位是最左边的位(字节序?)

Please correct me if any of those assumptions are wrong or if I have missed any.如果这些假设中有任何错误或我遗漏了任何假设,请纠正我。

使用 math.h 中的 signbit()。

Try尝试

float s = copysign(1, f);

from <math.h>来自<math.h>

Another helpful thing may be #including <ieee754.h> , if it's available on your system/compiler.另一个有用的东西可能是 #include <ieee754.h> ,如果它在您的系统/编译器上可用。

Assuming it's a valid floating point number (and not, for example, NaN):假设它是一个有效的浮点数(而不是,例如,NaN):

float f;
bool is_negative = f < 0;

It is left as an exercise to the reader to figure out how to test whether a floating point number is positive.留给读者的练习是弄清楚如何测试浮点数是否为正数。

1) sizeof(int) has nothing to do with it. 1) sizeof(int) 与它无关。

2) assuming CHAR_BIT == 8, yes. 2) 假设 CHAR_BIT == 8,是的。

3) we need MSB for that, but endianness affects only byte order, not bit order, so the bit we need to check is c[0]&0x80 for big endianness, or c[3]&0x80 for little, so it would be better to declare union with an uint32_t and checking with 0x80000000. 3)我们需要MSB,但字节序只影响字节顺序,而不是位顺序,所以我们需要检查的位是c[0]&0x80表示大端,或c[3]&0x80表示小,所以会更好用uint32_t声明联合并检查 0x80000000。

This trick have sense only for non-special memory operands.这个技巧只对非特殊内存操作数有意义。 Doing it to a float value that is in XMM or x87 register will be slower than direct approach.对 XMM 或 x87 寄存器中的float值执行此操作将比直接方法慢。 Also, it doesn't treat the special values like NaN or INF.此外,它不会处理像 NaN 或 INF 这样的特殊值。

Coming to this late, but I thought of another approach.来得这么晚,但我想到了另一种方法。

If you know your system uses IEEE754 floating-point format, but not how big the floating-point types are relative to the integer types, you could do something like this:如果您知道您的系统使用 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!
}

Essentially, you treat the bytes in your float as an unsigned integer type, then right-shift all but one of the bits (the sign bit) out of existence.本质上,您将浮点数中的字节视为无符号整数类型,然后将除一位(符号位)以外的所有位右移不存在。 '>>' works regardless of endianness so this bypasses that issue. '>>' 的工作与字节顺序无关,因此这绕过了该问题。

If it's possible to determine pre-execution which unsigned integer type is the same length as the floating point type, you could abbreviate this:如果可以在执行前确定哪个无符号整数类型与浮点类型的长度相同,则可以将其缩写为:

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

This worked on my test systems;这适用于我的测试系统; anyone see any caveats or overlooked 'gotchas'?有人看到任何警告或被忽视的“陷阱”吗?

google the floating point format for your system. google 系统的浮点格式。 Many use IEEE 754 and there is specific sign bit in the data to examine.许多使用 IEEE 754 并且数据中有特定的符号位要检查。 1 is negative 0 is positive. 1 为负 0 为正。 Other formats have something similar, and as easy to examine.其他格式也有类似的东西,而且很容易检查。

Note trying to get the compiler to exactly give you the number you want with a hard coded assignment like f = -0.0F;请注意,试图让编译器通过硬编码赋值(如 f = -0.0F;)准确地为您提供所需的数字; may not work.可能不起作用。 has nothing to do with the floating point format but has to do with the parser and the C/C++ library used by the compiler.与浮点格式无关,但与解析器和编译器使用的 C/C++ 库有关。 Generating a minus zero may or may not be that trivial in general.一般来说,生成负零可能是也可能不是那么简单。

I've got this from http://www.cs.uaf.edu/2008/fall/cs441/lecture/10_07_float.html try this:我从http://www.cs.uaf.edu/2008/fall/cs441/lecture/10_07_float.html得到这个试试这个:

/* 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;
}
(int)(x > 0) - (int)(x < 0);

为什么不if (f < 0.0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM