c中的否定浮点数在某些情况下会失败
我写了一个函数,它适用于数百种情况,但在某些情况下失败 下面是C函数:c中的否定浮点数在某些情况下会失败,c,bit-manipulation,C,Bit Manipulation,我写了一个函数,它适用于数百种情况,但在某些情况下失败 下面是C函数: unsigned negate_number(unsigned x) { int sign = (!(x & 0x80000000))<<31; int other = 0x7FFFFFFF & x; return (sign | other); } unsigned negate_数(unsigned x){ 整数符号=(!(x&0x8000000))我问: 当代码处理整数时,为什
unsigned negate_number(unsigned x) {
int sign = (!(x & 0x80000000))<<31;
int other = 0x7FFFFFFF & x;
return (sign | other);
}
unsigned negate_数(unsigned x){
整数符号=(!(x&0x8000000))我问:
当代码处理整数时,为什么要问标题中的“浮点数”问题?你是否试图用float
调用函数,并或多或少地将其视为一个位数组?如果是这样,你就处于隐藏状态!如果你在作用域中使用原型调用函数,C编译器将转换float
如果不在作用域中使用原型调用它,C编译器将在调用函数之前将浮点
转换为双精度
答复是:
这是一个32位的IEEE 754单精度数字。所以我只是翻转最重要的位(符号位)
要翻转32位(无符号整数)量的最高有效位,只需编写:
x ^= 0x80000000;
然而,正如我所指出的,除非你对你的编译器撒谎,否则你不会通过一个32位的浮点值
伪代码
文件A.c
文件B.c
然而,你在玩火,向你的编译器撒谎。编译器讨厌被欺骗,并且经常找到一种方法来找回自己。不要这样做!
主要是犹太法典
要以最少的问题(而不是“无问题”)或多或少达到您想要的效果,您可能需要:
文件B.c
严格地说,在分配给u.y
后读取和写入u.x
是未定义的行为,但它通常会执行您想要的操作;同样,在操作u.x
后返回u.y
所有这些都假设浮点
和无符号
的位布局是这样的:浮点
的符号位是无符号
的最高有效位当代码处理整数时,为什么要在标题中询问“浮点数”?是否尝试使用调用函数e> 浮点数
并或多或少地将其视为一个位数组?如果是这样,你就处于一个“无隐藏”状态!如果你在作用域中使用原型调用函数,C编译器将把浮点数
转换为无符号整数
。如果你不在作用域中使用原型调用它,C编译器将浮点数
转换为>在调用函数之前双击。它是一个32位IEEE 754单精度数字。因此我只是翻转最高有效位(符号位)。这对NaN(不是数字)失败输入。在这些情况下,如何使其具有故障安全性?@Anon如果您对NaN符号进行补码,它仍然是NaN-除非其他代码被破坏并且无法检测到这种NaN。我不能使用浮点作为类型。我必须使用无符号int作为类型。但输入将是32位单精度浮点数(IEEE 754)。您不理解我写的内容。函数的输入不能是32位的浮点
。您可以在调用代码中执行联合
操作,并将u.x
传递给您的函数。您也可以在否定编号()
中执行联合
操作。但您不能以编写代码的方式执行此操作。(或者,至少,我不认为您可以用编写代码的方式来完成。)[…继续…][…继续…]现在,如果调用代码中有一个unsigned
,其中包含与某个float
值相对应的位模式,那么当然可以将该unsigned int
传递给带有unsigned
参数和unsigned
返回值的函数,然后可以使用negate\u num的版本ber()
标记为“伪”。但您应该清楚,您传递的是一个无符号的(它恰好包含与某些浮点值相同的位模式),而不是浮点值本身。是的,输入是无符号的整数,它包含一些相应的浮点值,包括Nan(不是数字)如果将作为输入抛出,则需要返回。确定;因此您正在传递无符号的值。您的问题应该更清楚!根据,您可以翻转NaN的符号位,而不会真正影响它。如果您不想尝试(或冒风险)更改NaN,请检测NaN模式((x&0x7F100000)==0x7F100000)
并保持值不变。
extern float negate_number(float x);
...
float f1 = 3.14159;
float f2 = negate_number(f1);
...
unsigned negate_number(unsigned x)
{
return x ^ 0x80000000;
}
float negate_number(float f)
{
union { unsigned x; float y; } u;
u.y = f;
u.x ^= 0x80000000;
return u.y;
}