问题
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
floatand 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 thefloatto anunsigned int. If you don't call it with a prototype in scope, the C compiler will convert thefloatto adoublebefore 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