处理浮点数:特别是 numpy python

Dealing with floating points: With numpy python in particular

我想要像这样的值 - 1,1.02,1.04,1.06,1.08 等... 所以在 python:

中使用了 numpy
y = [x for x in numpy.arange(1,2,0.02)]

我得到了值-

1.0,
1.02,
1.04,
1.0600000000000001,
1.0800000000000001,

我这里有三个问题:

  1. 如何准确获取值 1,1.02,1.04,1.06,1.08 等....

  2. 为什么要更正 1.02 和 1.04 的值,而不是 1.0600000000000001,

  3. 当我们不能相信程序中的这些基本操作可以 运行 成数千行代码,并且我们在其中进行如此多的计算时,我们的程序有多可靠?我们如何应对这种情况?

有非常相似的问题解决一般浮点数问题,特别是 numpy 库问题 -

Is floating point math broken?

Why Are Floating Point Numbers Inaccurate?

虽然他们解决了为什么会发生这样的事情,但在这里我更关心的是如何在日常编程中处理这种情况,尤其是在 numpy 中 python?因此我有这些问题。

  • 第一个陷阱:不要混淆准确性和打印策略。

在你的例子中:

In [6]: [x.as_integer_ratio() for x in arange(1,1.1,0.02)]
Out[6]: 
[(1, 1),
 (2296835809958953, 2251799813685248),
 (1170935903116329, 1125899906842624),
 (2386907802506363, 2251799813685248),
 (607985949695017, 562949953421312),
 (2476979795053773, 2251799813685248)]

显示只有 1 个具有精确的浮点表示。

In [7]: ['{:1.18f}'.format(f) for f in arange(1,1.1,.02)]
Out[7]: 
['1.000000000000000000',
 '1.020000000000000018',
 '1.040000000000000036',
 '1.060000000000000053',
 '1.080000000000000071',
 '1.100000000000000089']

显示实习生准确性。

In [8]: arange(1,1.1,.02)
Out[8]: array([ 1.  ,  1.02,  1.04,  1.06,  1.08,  1.1 ])

显示 numpy 如何处理打印、四舍五入到最多 6 位数字、丢弃尾随 0。

In [9]: [f for f in arange(1,1.1,.02)]
Out[9]: [1.0, 1.02, 1.04, 1.0600000000000001, 1.0800000000000001, 1.1000000000000001]

显示了 python 如何处理打印、四舍五入到最多 16 位数字、丢弃第一位数字后的尾随 0。

  • 一些建议 我如何在日常编程中处理这种情况?

此外,对浮点数的每次操作都会降低准确性。
自然的 float64 精度大约是 1e-16,这对于很多应用程序来说已经足够了。减法是最常见的精度损失来源,如本例中精确结果为 0. :

In [5]: [((1+10**(-exp))-1)/10**(-exp)-1 for exp in range(0,24,4)]
Out[5]: 
[0.0,
 -1.1013412404281553e-13,
 -6.07747097092215e-09,
 8.890058234101161e-05,
 -1.0,
 -1.0]