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

Python 使用numpy.arange创建具有给定精度的浮点列表,python,numpy,Python,Numpy,我的目标是生成一个从1.0开始到1.499结束的编号列表,其中后续编号之间的步长为0.001。 最后,我加载一个包含一列浮点数的文件,例如,1.293,1.101,所有3个数字都超过了浮点数,我想在ls中查找从文件读取的每个数字出现的位置 创建ls的两种方法: 1. ls=np.arange(1,1.5,0.001) 及 2. 例如,根据1或2的任一方法,人们期望在ls中找到数字1.293,但情况似乎并非如此。例如,当我打印使用第二种方法创建的ls时,它会打印:[1.0,1.001,1.0019

我的目标是生成一个从
1.0
开始到
1.499
结束的编号列表,其中后续编号之间的步长为
0.001。

最后,我加载一个包含一列浮点数的文件,例如,
1.293,1.101,
所有3个数字都超过了浮点数,我想在
ls
中查找从文件读取的每个数字出现的位置

创建
ls
的两种方法:

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

2. 例如,根据1或2的任一方法,人们期望在ls中找到数字
1.293
,但情况似乎并非如此。例如,当我打印使用第二种方法创建的
ls
时,它会打印:
[1.0,1.001,1.00199999998,1.00299999997,
,而不是所需的
[1.0,1.001,1.002,1.003,…。

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

for i in range(len(ls)):
    print 'here ', i
    if ls[i] == 1.293: print 'Found'
它从不打印“find”,这意味着它不包含数字1.293,根据构造,它应该包含数字1.293,因为我在使用
np.arange
时给出了步长

  • 我应该如何创建
    ls
    ,以便真正获得
    1.0
    1.5
    之间的所有数字,步长
    0.001
    ,而不必处理更高的浮点精度

浮点数不是精确的实数,而是52位二进制小数中最接近的数字

例如,您不能将
1.001
放在二进制分数中;最接近的值是
1.000999999999889865875957184471189976
。如果将
0.001
添加到该值中,则与结果最接近的值是
1.00199999999999779731751914368942379951
。但最接近
1.002
的值是
1.0020000000000001776356839400250464678。这些不相等。它们在
2**52
中只相差一部分,但仍然不同

现在,您将
.001
添加到一个略小于
1.002
的数字中,这样错误可能会累积。最坏的情况是,您可以在
2**52
500次中减去一个部分,因此总错误可能与
2**52
中的500个部分一样严重,或者大约是
2**43
中的一个部分

解决这个问题的方法是永远不要检查两个浮点数是否相等;相反,用
math.isclose
np.isclose
计算出你的浮点数可能会导致多少错误,并检查它们是否在该错误范围内

在这种情况下,如果您只需要3位数的精度,并且可以确保最大误差永远不会接近这3位数,您可以简化事情,只检查它们是否在,比如说,
0.0001
。或者,更简单地说,您可以验证
isclose
使用的默认公差是否非常好够了,就用吧

因此,与此相反:

if ls[i] == 1.293:
……写下:

if math.isclose(ls[i], 1.293)

另一种方法是使用浮点十进制数,而不是浮点二进制数

当然,这些数字也有同样的问题——1/3不能完全适合十进制分数,就像它不能适合二进制分数一样。但是,如果你处理的数字只是十进制分数,比如
1/1000
,那就不是问题

而且,即使在出现问题时,能够选择精度而不必接受硬编码的精度,并且选择十进制数字而不是二进制数字,也可以使错误跟踪更容易考虑

唯一的问题是
decimal.decimal
值不是“本机的”对于您的CPU来说,十进制数学的运行速度大约要慢一个数量级,NumPy不知道如何处理十进制值,除非将其作为通用Python对象,因此它无法为您节省通常的空间和速度,等等。但是如果您只处理500个数字,谁在乎呢

因此:

如果你仔细想想,就可以很容易地简化事情,不需要所有的
Decimal(“…”)
构造函数,因为你的许多数字都是纯整数:

dist = int((Decimal('1.5')-1) * 1000)

这些只是浮点错误。你无法回避。你可以尝试使用
Decimal
对象列表。你可以使用Decimal库设置任意精度的浮点。非常棒,非常感谢你提供了如此有启发性的答案!我将使用
isclose
来实现它,这似乎是一个非常自然的解决方法und.我真的很困惑,问了这个问题,所以我非常感谢你的回答,尽管人们对我的问题投了反对票。@user929304作为旁注,如果你已经在使用numpy,你应该利用它。不要将数组转换成列表,也不要循环它;在数组上使用数组范围的操作。例如,
np.isclose(ls,1.293)
一次比较所有元素(比在它们上面循环更快,写/读也更短),并给出一个布尔数组,因此如果np.isclose(ls,1.293).any()
可以执行
,查看它们是否匹配。
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')
dist = int((Decimal('1.5')-1) * 1000)