避免浮点数的不准确性

Ahm*_*man 4 c floating-point precision numbers

我完全理解与浮点相关的问题,但我看到了一个我无法解释的非常有趣的行为.

float x = 1028.25478;
long int y = 102825478;
float z = y/(float)100000.0;
printf("x = %f ", x);
printf("z = %f",z);
Run Code Online (Sandbox Code Playgroud)

输出是:

x = 1028.254761 z = 1028.254780

现在,如果浮动数字在我将其分配给变量x时未能表示该特定随机值(1028.25478).为什么变量z的情况不一样?

PS我正在使用pellesC IDE来测试代码(C11编译器).

Ant*_*ala 5

我很确定这里发生的是后一个浮点变量被省略,而是保存在双精度寄存器中; 然后作为参数传递给printf.然后编译器会认为在默认参数提升后以双精度传递此数字是安全的.

我设法使用GCC 7.2.0 生成类似的结果,使用这些开关:

-Wall -Werror -ffast-math -m32 -funsafe-math-optimizations -fexcess-precision=fast -O3
Run Code Online (Sandbox Code Playgroud)

输出是

x = 1028.254761 z = 1028.254800
Run Code Online (Sandbox Code Playgroud)

那个数字略有不同^.

用于描述-fexcess-precision=fast说:

-fexcess-precision=style

此选项允许进一步控制浮点运算发生的机器上的过度精度,其格式的精度或范围比IEEE标准更高,并且交换浮点类型.默认情况下,-fexcess-precision=fast有效; 这意味着操作可以以比源中指定的类型更宽的精度执行,如果这将导致更快的代码,并且当舍入到源代码中指定的类型时,它是不可预测的.编译C时,如果-fexcess-precision=standard指定了if ,则多余的精度遵循ISO C99中规定的规则; 特别是,强制转换和赋值都会使值四舍五入到它们的语义类型(而-ffloat-store只影响赋值).-fexcess-precision=standard如果使用严格的一致性选项,-std=c99则默认情况下为C启用此选项[ ] . 默认情况下-ffast-math 启用-fexcess-precision=fast,无论是否使用严格的一致性选项.

此行为不符合C11