c - 在某些情况下,c 中的负 float 会失败

标签 c bit-manipulation

我编写了一个函数,该函数适用于数百种情况,但在某些情况下会失败。

这是 C 函数:

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

我只是屏蔽符号,将其反转并与屏蔽指数和曼特萨进行 OR(连接)。所以这应该适用于所有情况。

但这里有一个失败的情况: x = 0x7fc00000 (2143289344)

最佳答案

我问:

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.

回应是:

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

要翻转 32 位(无符号整数)数量的最高有效位,您可以简单地编写:

x ^= 0x80000000;

但是,正如我所指出的,除非您对编译器撒谎,否则根本不会传递 32 位 float 。如果你有以下条件,你就可以“让它工作”(在某些机器上,有时):

虚假代码

文件A.c

extern float negate_number(float x);

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

文件B.c

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

但是,您正在对编译器玩火和撒谎。编译器讨厌被欺骗,并且经常想办法挽回自己的损失。 不要这样做!

主要是犹太洁食代码

要以最少的问题(但不是“没有问题”)或多或少地实现您想要的效果,您可能需要:

文件B.c

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

严格来说,在分配给 u.y 后读取和写入 u.x 是未定义的行为,但它通常会执行您想要的操作;与操作 u.x 后返回 u.y 类似。

所有这些都假设 floatunsigned 的位布局使得 float 的符号位是最高有效位无符号

关于c - 在某些情况下,c 中的负 float 会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12336675/

相关文章:

c - 函数和字符串,检查输入字符串是否匹配

连接宏名称

c - 使用位运算符的效率

javascript - 将 javascript 双按位转换为 C#

c - 获取程序背后的代码

c - 使用 memcpy 将结构复制到堆中

c - 操作字符变量的位

java - 反转二进制字符串java的位

c - 7段LED + 4094

基于K&R的C语言中各种I/O函数的比较