为什么这两个代码片段会产生不同的结果? (浮动,双精度)

时间:2012-01-25 11:02:03

标签: c++ floating-point double precision

我只是开始学习C ++并且一直在搞乱浮点值和双值。下面是两个代码片段,在我看来,它们做同样的事情,但给出了不同的结果。我错过了什么?有人可以解释第一个代码必须具有的精度误差,以获得与第二个不同的结果。

int _tmain(int argc, _TCHAR* argv[])
{
    const float f = 0.1;
    const double d = 0.1;
    int counter = 0;

    for(counter; ((double)counter * f - (double)counter * d) < 0.34; counter++) {}

    cout << "Iterations = " << counter << "\n" ;

    system("pause");
    return 0;
}


int main (int argc, const char * argv[])
{
    float time_f = 0.1;    
    double time_d = 0.1;
    float total_f = 0;
    double total_d = 0;
    int count=0;
    double difference = 0;
    while (true) {
        total_d = count * time_d;
        total_f = count * time_f;
        if(total_f - total_d >= 0.34){

            break;
        }
        count++;

    }
    std::cout <<  count << "\n";
    system("pause");
}

我在float和double之间修改了for循环条件的强制转换,但值没有差别。

3 个答案:

答案 0 :(得分:2)

floatdouble都有一个有限的表示,这意味着它们 采取一系列离散值,而不仅仅是任何真正的价值。在 特别是,在您的示例中,0.1没有确切的浮点数 在我所知道的任何现代机器上的表示(所有这些都使用基础 在实现中它是2的幂 - 0.11/5 * 1/2,没有任何1/5的倍数可以有限 表示除非基数是5的倍数。

结果是floatdouble具有相同的基础 表示(通常不是这种情况),或者会有差异 count与0不同。

这个主题的通常参考是 “什么 每个计算机科学家都应该知道浮点数 算术”。直到你阅读和理解(或至少 理解其含义)它,你不应该触摸机器漂浮 点。

答案 1 :(得分:1)

这两个代码片段之间的区别在于强制转换。 counter * f被转换为在第一个片段中加倍并在第二个片段中存储为浮点变量。

以下是它的外观示例:

#include <stdio.h>

int main(int argc, char* argv[])
{
    const float f = 0.1;
    const double d = 0.1;
    int count = 0;

    for(count; (double)(count * f) - (double)(count * d) < 0.34; count++);

    printf("Iterations = %d\n", count);
    count = 0;

    while (true)
    {
        double total_d = count * d; // is equal to (double)(count * d)
        double total_f = count * f; // is equal to (double)(count * f)
        if (total_f - total_d >= 0.34)
            break;
        count++;
    }
    printf("Iterations = %d\n", count);

    return 0;
}

答案 2 :(得分:0)

你还没有计算加倍数:

total_d = count * time_d;
total_f = count * time_f;

另一方面,这些循环永远不会结束,因为两个减法操作数具有相同的值:S