浮点精度细微差别

时间:2010-06-15 18:38:15

标签: c floating-point

我在NVIDIA的CUDA SDK示例中找到了此代码。

void computeGold( float* reference, float* idata, const unsigned int len)
{
    reference[0] = 0;
    double total_sum = 0;
    unsigned int i;
    for( i = 1; i < len; ++i)
    {
        total_sum += idata[i-1];
        reference[i] = idata[i-1] + reference[i-1];
    }
    // Here it should be okay to use != because we have integer values
    // in a range where float can be exactly represented
    if (total_sum != reference[i-1])
        printf("Warning: exceeding single-precision accuracy.  Scan will be inaccurate.\n");
}
//(C) Nvidia Corp

有人可以告诉我一个会打印警告的情况,最重要的是,为什么。

3 个答案:

答案 0 :(得分:5)

通常,您不能对许多浮点数求和。

最终,总和变得与每个新添加的数字不同,因此精度会丢失。例如,在浮动的情况下,添加一百万个相同数量级的数字会得到与一千万个相同的结果,因为到它完成时,每添加一个新数字都不会改变任何东西。

围绕这个的算法涉及每增加一个数字的几次乘法(实际上,只是为了正确地对数字求和)。是的,浮点很棘手。

请参阅http://floating-point-gui.de/

答案 1 :(得分:2)

该功能在编写时考虑了一定范围的输入数据。如果未满足输入数据期望,则会打印警告:

#include <stdio.h>
#define COUNT_OF(x) (sizeof(x)/sizeof(0[(x)]))

void computeGold( float* reference, float* idata, const unsigned int len)
{
    double total_sum = 0;
    unsigned int i;

    reference[0] = 0;

    for( i = 1; i < len; ++i)
    {
        total_sum += idata[i-1];
        reference[i] = idata[i-1] + reference[i-1];
    }
    // Here it should be okay to use != because we have integer values
    // in a range where float can be exactly represented
    if (total_sum != reference[i-1])
        printf("Warning: exceeding single-precision accuracy.  Scan will be inaccurate.\n");
}
//(C) Nvidia Corp


float data[] = {
    1.0,
    2.0,
    3.0,
    4.0,
    5.0
};

float data2[] = {
    123456.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    999999.0,
    123456.0
};

float ref[COUNT_OF(data2)] = {0.0};

int main()
{
    computeGold( ref, data, COUNT_OF(data));
    computeGold( ref, data2, COUNT_OF(data2));
    return 0;
}

答案 2 :(得分:1)

float通常具有类似+/- 1e38的范围,但精度仅为大约5或6位数。这意味着,例如,可以存储类似12345678的内容,但它只能以大约6位精度存储,因此您将收到警告。