C和铸造 - 为什么这个程序在6点停止?

时间:2012-09-06 13:59:38

标签: c casting

我为我的作业编辑了一个C程序,之前没有进行类型转换,迭代在i = 1处停止,现在通过类型转换,它停止在i = 6。

任何想法为什么?提前谢谢!

int main(void)
{

    int i = 0;
    double d = 0.0;

    while ( (i == (int) (d * 10)) && (i < 10) )
    {
        i = i + 1;
        d = (double) (d + 0.1);
        printf("%d %lf\n", i, d);
    }

    printf("%d %lf\n", i, d);

    getch();

    return 0;
}

3 个答案:

答案 0 :(得分:4)

浮点运算是不精确的。值0.1在二进制浮点中不能完全表示。这里推荐的读数是:What Every Computer Scientist Should Know About Floating-Point Arithmetic

在程序中的某个时刻,由于舍入错误,d略小于i/10,因此您的循环终止。

答案 1 :(得分:2)

除了其他答案之外,我想回答一个问题,为什么循环先于条件i == (d * 10)而不是i == (int) (d * 10)终止。

在第一种情况下,int左侧的==值被提升为加倍,因此当d*10中的累积误差为正或负时(例如, 0.999999或1.000001)。

在第二种情况下,右侧被截断为int,因此不等式仅在误差为负时发生(例如5.999999)。因此,第一个版本会提前失败。

答案 2 :(得分:1)

正如之前多次提到的,这不起作用的原因是二进制浮点数不能代表所有十进制浮点二进制数,它是不可能的。要了解更多信息,请查看这篇非常棒的文章:

What Every Programmer Should Know About Floating-Point Arithmetic

现在,在更实际的方面,当使用浮点并将其与另一个数字进行比较时,您应该几乎总是round该值或使用epsilon值,如下所示:

if (ABS(doubleValue - intValue) < 0.00001) // 0.00001 is a margin-of-error for floating point arithmetic
    // the two numbers are even (or close to it)