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
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)