使用numpy.arange创建具有给定精度的浮点列表

时间:2018-07-31 15:28:17

标签: python numpy

我的目标是生成一个数字列表ls,该列表从1.01.499结束,其中后续数字之间的步长为0.001.

最终,我正在加载一个文件,该文件具有一列浮点数,例如1.293, 1.101, ...,所有浮点数后有3个数字,并希望查找从ls中读取的每个数字的位置文件发生。

我创建ls的两种方法:

1

ls = np.arange(1.,1.5,0.001)

2

ls = []
t = 1.0
dist = int((1.5-1.)/0.001)
for i in range(dist):
    ls.append(t)
    t+=0.001

根据1或2的方法,例如,希望以ls查找数字1.293,但事实并非如此。例如,当我打印使用第二种方法创建的ls时,它打印:[1.0, 1.001, 1.0019999999999998, 1.0029999999999997,...而不是所需的[1.0, 1.001, 1.002, 1.003, ...].

另一方面,使用第一种方法创建ls,并测试是否再次找到数字1.293,如下所示:

for i in range(len(ls)):
    print 'here ', i
    if ls[i] == 1.293: print 'Found'

它从不打印“ Found”,这意味着它不包含数字1.293,根据构造,在使用np.arange时,它将包含我给出的步长。

  • 我应该如何创建ls,这样我才能真正获得1.01.5之间的所有数字,步长为0.001,而不必处理更高的精度浮点数。

1 个答案:

答案 0 :(得分:2)

浮点数不是精确的实数,而是可以放入52位二进制分数中的最接近的数。

例如,您不能将1.001放入二进制分数;最接近的值为1.000999999999999889865875957184471189976。如果将0.001添加到该值,则与结果最接近的值为1.001999999999999779731751914368942379951。但是最接近1.002的值是1.002000000000000001776356839400250464678。那些不相等。它们在2**52中仅相差一个部分,但仍存在差异。

现在您将.001加到一个比1.002小一些的数字上,这样错误就会累积起来。最坏的情况是,您可能在2**52中造成500倍的误差,因此总误差可能高达2**52中500的误差,或者在2**43中的1误差。 >

处理该问题的方法是永远不要检查两个浮点数是否相等;相反,请使用math.isclosenp.isclose来计算您的浮点数学运算会引入多少误差,并检查它们是否在该误差范围内。

在这种情况下,您只需要3位数的精度,并且可以确定最大误差永远不会接近这3位数,您可以简化内容并检查它们是否在{{{ 1}}。或者,甚至更简单地,您可以验证0.0001使用的默认公差是否足够好,然后使用它们即可。

所以,代替这个:

isclose

…写下:

if ls[i] == 1.293:

另一种方法是使用浮点数十进制代替浮点数 binary

当然,它们也有相同的问题-1/3不能精确地适合小数部分,也不能完全适合二进制部分。但是,如果您要处理的唯一数字是小数,例如if math.isclose(ls[i], 1.293) ,那就没问题了。

而且,即使是 问题,能够选择精度而不是必须接受硬编码的精度,并以十进制数字而不是二进制数字进行选择,也会导致错误跟踪想起来容易得多。

唯一的问题是1/1000值不是CPU的“本机”。十进制数学的运行速度大约慢了一个数量级,NumPy除了作为通用Python对象外,不知道如何处理十进制值,因此它无法为您提供通常的空间和速度节省等。但是,如果您仅处理500个号码,谁在乎?

所以:

decimal.Decimal

如果考虑到这一点,很容易将其简化为不需要所有这些from decimal import Decimal ls = [] t = Decimal('1.0') dist = int((Decimal('1.5')-Decimal('1.'))/Decimal('0.001')) for i in range(dist): ls.append(t) t+=Decimal('0.001') 构造函数,因为许多数字只是纯整数:

Decimal('…')