Python 到 C 浮点不精确

Python to C Floating Point Imprecision

从 Python 中创建的 csv 文件导入浮点数到用 C 编写的程序时,我遇到了一些精度问题。以下代码是我的程序中发生的情况的示例:Python 将 float32 值写入文件(在本例中为 9.8431373e+00),我将其读入字符串并使用 strtof 将其转换回 float32,但结果在最后一个小数位上有所不同。

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

int main(void) {
    
    char* a;
    char x[10] = "9.8431373";
    printf("%s\n", x);
    float f = strtof(x,&a);
    printf("%.7e\n", f);
}

输出:

9.8431373
9.8431377e+00

现在,如果我错了,请纠正我,但是 C 中的 float 对象有 32 位,无论它的浮点数是多少,它都会导致 7 位小数的精度。所以如果我没有声明一个大于浮点数允许的数字,就不会有任何精度错误。

如果我确实声明了一个比 C 中允许的 float 更精确的数字,那么 Python 如何在不更正的情况下将“9.8431373e+00”接受为 Float32? Python 和 C 对 32 位浮点数有不同的标准吗?

Python 默认解释为 double。如果您打包为单精度并再次解包,您会在 Python 中看到相同的问题:

>>> import struct
>>> a = struct.pack('<f', 9.8431373)
>>> b, = struct.unpack('<f', a)
>>> b
9.843137741088867

从根本上说,小数部分 9.8431373 在二进制浮点数中不存在,无论是单精度 (float) 还是双精度。作为 32 位 float,您可以获得的最接近的是一个二进制数,相当于大约 9.84313774,而作为 double,您可以获得的最接近的是一个对应于大约 9.8431373000000004 的数字。

这取决于您和您的编程语言的某种组合,这些数字如何以十进制显示给您。有时它们是圆形的,有时它们是截短的。我不太了解 Python,但我知道它的规则至少与 C 的规则有一点不同,所以你看到最后一位数字相差 1 我并不感到惊讶。