Rosenbrock测试函数计算的准确性

活力

我想计算Rosenbrock的测试函数

在此处输入图片说明

我已经实现了以下C / C ++代码

#include <stdio.h>

/********/
/* MAIN */
/********/
int main()
{
    const int N = 900000;

    float *x = (float *)malloc(N * sizeof(float));
    for (int i=0; i<N; i++) x[i] = 3.f;

    float sum_host = 0.f;
    for (int i=0; i<N-1; i++) {
        float temp = (100.f * (x[i+1] - x[i] * x[i]) * (x[i+1] - x[i] * x[i]) + (x[i] - 1.f) * (x[i] - 1.f));
        sum_host = sum_host + temp;
        printf("%i %f %f\n", i, temp, sum_host);
    }
    printf("Result for Rosenbrock's test function calculation = %f\n", sum_host);

}

由于将x数组初始化为3.f,则每个求和项应为3604.f,因此涉及899999的最终求和应为3243596396但是,我得到的结果是3229239296,绝对误差为14357100如果我测量两个连续的部分求和之间的差,我会发现它是3600.f用于早期的部分求和,然后下降到3584最后的部分求和,而应该始终为3604.f

如果我使用Kahan求和算法作为

sum_host = 0.f;
float c        = 0.f;
for (int i=0; i<N-1; i++) {
    float temp = (100.f * (x[i+1] - x[i] * x[i]) * (x[i+1] - x[i] * x[i]) + (x[i] - 1.f) * (x[i] - 1.f)) - c;
    float t    = sum_host + temp;
    c          = (t - sum_host) - temp;
    sum_host = t;
}

我得到的结果是3243596288,绝对误差小得多108

我非常确定,我看到的这种效果应该归因于浮点运算的精度。有人可以确认这一点,并向我解释发生这种情况的机制吗?

Tmyklebu

您可以temp = 3604.0f在每次迭代中准确地进行计算。当您尝试添加3604.0f其他内容并将结果四舍五入到最接近值时,就会出现问题floatfloats存储一个指数和23位有效数字,这意味着相隔24位以上的1位结果将四舍五入为除它以外的其他值。

请注意,3604 = 901 * 4,且901的二进制扩展为1110000101;当您开始添加temp大于2 ^ 24 * 4 = 67108864的内容时,您将开始看到四舍五入。(这也发生在您运行代码时;当sum_host超过67108864时,它会开始打印出3600,因为连续sum_host的右边之间存在差异。 )当您添加temp大于2 ^ 26 * 4的东西时,您开始看到甚至更多的舍入那时,第二个最小的“ 1”位也被吞咽了。

请注意,在进行Kahan求和后,sum_host您将报告ANDc-108这很松散,因为c它一直在跟踪接下来的最高24位。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章