浮点数的符号

发布于 2024-10-03 04:46:28 字数 490 浏览 4 评论 0原文

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

我进行了实验并想出了这个:

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

其中 (c[3] & 0x10000000) 给出了一个值 > 0 代表负数,但我认为这需要我做出以下假设:

  • 机器的字节是 8 位大
  • 浮点数是 4 字节大?
  • 该机器的最高有效位是 最左边的位(字节顺序?)

如果这些假设有任何错误或者我遗漏了任何假设,请纠正我。

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:

  • The machine's bytes are 8 bits big
  • a float point number is 4 bytes big?
  • 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

空心↖ 2024-10-10 04:46:28

使用 math.h 中的signbit()。

Use signbit() from math.h.

梦醒灬来后我 2024-10-10 04:46:28

尝试

float s = copysign(1, f);

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

Try

float s = copysign(1, f);

from <math.h>

Another helpful thing may be #including <ieee754.h>, if it's available on your system/compiler.

笑,眼淚并存 2024-10-10 04:46:28

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

float f;
bool is_negative = f < 0;

留给读者作为练习,弄清楚如何测试浮点数是否为正数。

Assuming it's a valid floating point number (and not, for example, 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.

清音悠歌 2024-10-10 04:46:28

1) sizeof(int) 与之无关。

2) 假设 CHAR_BIT == 8,是的。

3) 为此,我们需要 MSB,但字节顺序仅影响字节顺序,而不影响位顺序,因此我们需要检查的位是 c[0]&0x80 以获得大字节顺序,或 c [3]&0x80 的作用很小,因此最好使用 uint32_t 声明并集并使用 0x80000000 进行检查。

这个技巧仅对非特殊内存操作数有意义。对 XMM 或 x87 寄存器中的 float 值执行此操作将比直接方法慢。此外,它不处理 NaN 或 INF 等特殊值。

1) sizeof(int) has nothing to do with it.

2) assuming CHAR_BIT == 8, yes.

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.

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. Also, it doesn't treat the special values like NaN or INF.

爱她像谁 2024-10-10 04:46:28

谷歌搜索适合您系统的浮点格式。许多使用 IEEE 754,数据中有特定的符号位需要检查。 1 为负 0 为正。其他格式也有类似的东西,并且很容易检查。

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

google the floating point format for your system. Many use IEEE 754 and there is specific sign bit in the data to examine. 1 is negative 0 is positive. 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; 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. Generating a minus zero may or may not be that trivial in general.

虽然来晚了,但我想到了另一种方法。

如果您知道您的系统使用 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!
}

本质上,您将浮点数中的字节视为无符号整数类型,然后右移除一位(符号位)之外的所有位。 '>>'无论字节序如何,都可以工作,因此这可以绕过该问题。

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

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

这在我的测试系统上有效;有人看到任何警告或被忽视的“陷阱”吗?

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:

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'?

梦归所梦 2024-10-10 04:46:28

我从 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;
}

I've got this from http://www.cs.uaf.edu/2008/fall/cs441/lecture/10_07_float.html
try this:

/* 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;
}
自找没趣 2024-10-10 04:46:28
(int)(x > 0) - (int)(x < 0);
(int)(x > 0) - (int)(x < 0);
孤独患者 2024-10-10 04:46:28

为什么不if (f < 0.0)

Why not if (f < 0.0)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文