C 上的机器 epsilon

har*_*ter 1 c floating-point

printf为什么如果存在强制转换,下面的两个语句会打印相同的值(float),但如果删除强制转换,则不会打印相同的值?

#include <float.h>
#include <stdio.h>

int main(void)
{
    float eps = 1.0;
    while ((float)(1 + eps/2.0) != 1.0)
        eps /= 2.0;

    printf("%e\n", eps);
    printf("%e\n", FLT_EPSILON);
}
Run Code Online (Sandbox Code Playgroud)

zwo*_*wol 8

随着编程语言的发展,C 非常乐意以比您预期更广泛的类型进行算术运算。在这种情况下,表达式

eps/2.0
Run Code Online (Sandbox Code Playgroud)

转换epsdouble除法之前的值,因为数值常量的2.0类型为double。您可以通过编写来避免这种情况2.0f,但即便如此,有一条规则规定,只要记录了选择,编译器就可以执行所有浮点算术。(C2011 第 5.2.4.2.2 节,第 9 段。)doublelong double

通过实现 where FLT_EVAL_METHOD == 0,您可以通过编写来避免强制转换

    float eps = 1.0f;
    while (1.0f + eps/2.0f != 1.0f)
        eps /= 2.0f;
Run Code Online (Sandbox Code Playgroud)

但如果FLT_EVAL_METHOD非零,则您的演员阵容是必要的。