gpt4 book ai didi

c - C 实现中的浮点零(IEEE 754 不变量?)

转载 作者:太空狗 更新时间:2023-10-29 15:03:37 25 4
gpt4 key购买 nike

我有以下 C 表达式(变量是 32 位 float )

float result = (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0)

假设 x0==x1y0==y1,(== 我指的是二进制表示标识),我可以依赖于表达式必须计算为零的事实(例如, float 的所有位都设置为 0)?换句话说,我可以假设以下不变量始终成立吗?

memcmp(&a, &b, sizeof(float) == 0 => memcmp(a-b, (uint32_t)0, sizeof(float)) == 0
0*a == 0.0

可以安全地假设所有值都是有限数(没有 INFINITY 或 NaN)。

编辑:正如答案中所指出的,与 0 的乘法可以产生带符号的零。我是否仍然可以相信使用 FP 比较规则表达式的结果将等于 0.0,即:

(result == 0.0) 

编辑 1:用 memcmp 调用替换类型转换以更好地说明问题。

附言我将我的代码限制为仅适用于兼容的 C11 编译器,以防万一。如果这对我的情况有帮助,我也愿意依靠 STDC_IEC_559 支持。

最佳答案

提及 C11 只会混淆您的问题,因为任何 C 标准都不需要 IEEE 754。

也就是说,只要假设 IEEE 754 32 位 float 并且不对 x2y2 做任何假设(除了它们不是无穷大或 NaN)你可以不要假设结果的所有位都为 0。IEEE 754 数字有两个零,一个为负,一个为正,如果表达式 (y2 - y0) - (x2 - x0) 为负,它与零相乘的结果将是负零。

我们可以用这个简短的例子来测试它:

#include <stdio.h>
#include <stdint.h>

int
main(int argc, char **argv)
{
union {
float f;
uint32_t i;
} foo;

float a = 0;
float b = -1;

foo.f = a * b;
printf("0x%x\n", foo.i);

return 0;
}

结果(注意没有优化,因为我不希望编译器变得聪明):

$ cc -o foo foo.c && ./foo
0x80000000

哦,我刚刚注意到你所说的“换句话说”问题的第二部分实际上并不是换句话说,因为这是一个不同的问题。

开始于:

(*(uint32_t*)(&a) == *(uint32_t*)(&b))

不等同于 a == b 的 float ,因为 -0 == 0。这样一来,假设的另一部分就不成立了,因为 -0 - 0 给了你 -0。我无法让任何其他相等数字的减法产生负零,但这并不意味着它不可能,我很确定标准不会在所有实现上强制执行相同的减法算法所以符号位可能会以某种方式潜入其中。

关于c - C 实现中的浮点零(IEEE 754 不变量?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38350731/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com