negate floating number in c fails in some cases

梦想与她 提交于 2019-12-02 22:57:40

问题


I wrote a function which works for hundreds of cases but fails in some cases.

Here is the C function:

unsigned negate_number(unsigned x) {
  int sign = (!(x & 0x80000000))<<31;
  int other = 0x7FFFFFFF & x;
  return (sign | other);
}

I am just masking sign, inverting it and doing a OR (joining) with masked exponent and mantessa. So this should work in all cases.

But here is a case where it fails: x = 0x7fc00000 (2143289344)


回答1:


I asked:

Why are you asking about 'floating number' in the title when the code is working with integers? Are you trying to call the function with a float and treat it as an array of bits, more or less? If so, you're on a hiding to nothing! If you call the function with a prototype in scope, the C compiler will convert the float to an unsigned int. If you don't call it with a prototype in scope, the C compiler will convert the float to a double before calling the function.

And the response was:

It is a 32 bit IEEE 754 single precision number. So I am just flipping the most significant bit (sign bit).

To flip the most significant bit of a 32-bit (unsigned integer) quantity, you could simply write:

x ^= 0x80000000;

However, as I indicated, you are simply not getting passed a 32-bit float unless you are lying to your compiler. You could 'get it to work' (on some machines, some of the time) if you had:

Bogus Code

fileA.c

extern float negate_number(float x);

...
float f1 = 3.14159;
float f2 = negate_number(f1);
...

fileB.c

unsigned negate_number(unsigned x)
{
    return x ^ 0x80000000;
}

However, you are playing with fire and fibbing to your compiler. Compilers hate being lied to and often find a way to get their own back. Do Not Do This!

Mostly kosher code

To achieve more or less the effect you want with a minimum of issues (but not 'no issues'), you probably need:

fileB.c

float negate_number(float f)
{
    union { unsigned x; float y; } u;
    u.y = f;
    u.x ^= 0x80000000;
    return u.y;
}

Strictly, reading and writing to u.x after assigning to u.y is undefined behaviour, but it will normally do what you want; similarly with returning u.y after manipulating u.x.

All of this assumes that the bit layout of float and unsigned are such that the sign bit of the float is the most significant bit of the unsigned.



来源:https://stackoverflow.com/questions/12336675/negate-floating-number-in-c-fails-in-some-cases

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!