Python 和 C 中梯形规则的精度

precision of trapezoidal rule in Python and C

我在 Python 中编写了集成代码,并使用梯形法则在 C 中再次编写了代码。任务是从 file 中读取数据并随着时间的推移对速度进行积分。将数据文件复制到我的工作目录后,我编译并 运行 以下程序。 C 程序给了我 8.218921,而 Python 程序给了我 8.218924000000003。这两个值小数点后6位不同

差异从何而来?

这是我的 C 程序。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int
main (void)
{

    FILE *fptr;
    if((fptr = fopen("velocities.txt", "r"))==NULL){
        printf("cannot open the file\n");
        exit(1);
    }

    printf("file opened\n");

    int t[200] = {};
    double v[200] = {};
    int n = 0;

    while( (fscanf(fptr, "%d\t %lf\n", &t[n], &v[n])!=EOF) && (n<200) ){
        printf("%d\t %lf\n", t[n], v[n]);
        n++;
    }

    int h = 0;
    float area = 0.0;
    printf("calculating the travel distance\n");
    for(int i=1;i<n;i++){
        h = t[i]-t[i-1];
        area += (v[i]+v[i-1])*h/2;
    }
    printf("area : %lf\n", area);


    fclose(fptr);

    return 0;
}

这是 Python 个代码。

import numpy as np

arr = np.loadtxt("./velocities.txt")
arr = arr.T

h, area = 0, 0

for i in range(1, 101):
    h = arr[0,i] - arr[0,i-1]
    area += (arr[1,i]+arr[1,i-1])/2

print(area)

结果可能是正确的,这是由于precision with floating numbers

几乎每种语言都会发生这种情况,您的 C 程序可能只是将它隐藏在这里。

不同之处在于,尽管 double v[200] = {}; 具有双精度,但 float area = 0.0; 是一个 floating-point 数字,因此会损失一半的精度。

Python 将默认使用 double,从而保持精度。


如您所见,floating-point 个数字很快失去精度:

#include <stdio.h>

int main()
{
    float pi_flt = ((float)22)/7;
    double pi_dbl = ((double)22)/7;

    printf("%.8f, %.8lf\n", pi_flt, pi_dbl);
    return 0;
}

编译并运行:

$ clang -Weverything test.c
test.c:9:29: warning: implicit conversion increases floating-point precision: 'float'
      to 'double' [-Wdouble-promotion]
    printf("%.8f, %.8lf\n", pi_flt, pi_dbl);
    ~~~~~~                  ^~~~~~
1 warning generated.
$ ./a.out
3.14285707, 3.14285714