-1

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

这是C函数:

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

我只是在掩蔽符号,将其反转并使用掩蔽指数和 mantessa 进行 OR(连接)。所以这应该适用于所有情况。

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

4

1 回答 1

1

我问:

当代码使用整数时,为什么要在标题中询问“浮点数”?您是否尝试使用 a 调用该函数float并将其视为或多或少的位数组?如果是这样,你就什么都没有了!float如果您在范围内使用原型调用函数,C 编译器会将unsigned int. 如果您不使用范围内的原型调用它,C 编译器将在调用函数之前将其转换float为 a 。double

回应是:

它是一个 32 位 IEEE 754 单精度数。所以我只是翻转最重要的位(符号位)。

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

x ^= 0x80000000;

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

假代码

文件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.x严格来说,在赋值后读写u.y是未定义的行为,但它通常会做你想做的事;u.y与操作后返回类似u.x

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

于 2012-09-09T05:35:48.783 回答