【问题标题】:Floats being Inexact浮动不精确
【发布时间】:2013-08-11 00:58:58
【问题描述】:

我很困惑。我无法解释为什么在使用 double 数据类型时此测试通过但在使用 float 数据类型时失败。考虑下面的 sn-p 代码。

float total = 0.00;

for ( int i = 0; i < 100; i++ ) total += 0.01;

人们会预计 total 为 1.00,但它等于 0.99。为什么会这样?我用 GCC 和 clang 编译,两个编译器的结果是一样的。

【问题讨论】:

  • “使用double数据类型时测试通过”是什么意思?无论您使用哪种浮点数据类型,此“测试”都不会在 total 中生成 1.0
  • 使用float,我得到0.999999344348907470703125;与double 我得到1.0000000000000006661338147750939242541790008544921875。 YMMV。

标签: c gcc clang c99


【解决方案1】:

试试这个:

#include <stdio.h>

int main(){
    float total = 0.00;
    int i;
    for (i = 0; i < 100; i++)
        total += 0.01;

    printf("%f\n", total);

    if (total == 1.0)
        puts("Precise");
    else
        puts("Rounded");
}

至少在大多数机器上,您会得到“圆角”的输出。换句话说,结果恰好足够接近,以至于当它被打印出来时,它是四舍五入的,所以它看起来正好是 1.00,但实际上不是。将total 更改为double,您仍然会得到相同的结果。

【讨论】:

    【解决方案2】:

    0.01 的十进制值表示为系列:a1*(1/2) + a2*(1/2)^2 + a3*(1/2)^4 + etc. 其中aN 是零或一。

    我留给您计算 a1、a2 的具体值以及需要多少小数位 (aN)。在某些情况下,小数部分不能由 (1/2)^n 值的有限系列表示。

    要使这个系列在十进制中求和为 0.01,aN 需要超出存储在浮点数中的位数(全字位数减去符号和指数的位数)。但是由于 double 具有更多位,因此可以/可能/可能(您进行计算)精确定义 0.01 十进制。

    【讨论】:

    • 十进制 0.01 没有精确的有限二进制展开。
    • @caf:确切的infinite二进制扩展是0.0 0011 0011 0011 ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    相关资源
    最近更新 更多