MrM*_*ter 5 c numeric zero ieee-754
我有一个以下的C表达式(变量是32位浮点数)
float result = (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0)
Run Code Online (Sandbox Code Playgroud)
假设x0==x1和y0==y1,(并且==我的意思是二进制表示形式),我可以依赖表达式必须求值为零的事实(例如,浮点数的所有位都设置为0)?换句话说,我可以假设跟随不变量总是持有吗?
memcmp(&a, &b, sizeof(float) == 0 => memcmp(a-b, (uint32_t)0, sizeof(float)) == 0
0*a == 0.0
Run Code Online (Sandbox Code Playgroud)
可以安全地假设所有值都是有限数(无INFINITY或NaN).
编辑:正如答案中所指出的,乘以0会产生带符号的零.我仍然可以依赖于使用FP比较规则表达式的结果将等于0.0的事实,即:
(result == 0.0)
Run Code Online (Sandbox Code Playgroud)
编辑1:通过memcmp调用替换类型转换以更好地说明问题.
PS我只是将我的代码限制在兼容的C11编译器中,以防它有任何区别.如果这对我的情况有帮助,我也愿意依赖STDC_IEC_559支持.
提及 C11 只会让你的问题感到困惑,因为任何 C 标准都不要求 IEEE 754。
话虽这么说,只是假设 IEEE 754 32 位浮点数并且不对 和 做任何假设x2(y2除了它们不是无限或 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;
}
Run Code Online (Sandbox Code Playgroud)
结果(注意没有优化,因为我不希望编译器变得聪明):
$ cc -o foo foo.c && ./foo
0x80000000
Run Code Online (Sandbox Code Playgroud)
哦,我刚刚注意到你所说的问题的第二部分“换句话说”实际上并不是换句话说,因为这是一个不同的问题。
首先:
(*(uint32_t*)(&a) == *(uint32_t*)(&b))
Run Code Online (Sandbox Code Playgroud)
不等于a == b浮点数,因为-0 == 0. 这样一来,假设的另一部分就崩溃了,因为-0 - 0给了你-0。我无法对相等的数字进行任何其他减法生成负零,但这并不意味着这是不可能的,我很确定标准不会在所有实现上强制执行相同的减法算法,因此标志位可能会以某种方式潜入那里。
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |