将数组转换为列表

时间:2015-06-12 10:45:24

标签: python arrays list numpy floating-point

我正在使用Numpy和ode在Python中进行相当多的科学数值集成。我使用了几个数组,我想将1d数组转换为导出和更容易操作的列表。从那以后,我发现了更简单,更灵巧的方法,而没有求助于列表,但在此之前,我偶然发现了这个奇怪的不需要的行为,我无法找到解释。我在结果中剪断了数组,但这是整个代码。

如果我使用arange

创建范围数组

a=numpy.arange(1,20,0.2)

结果是

array([ 1. , 1.2, 1.4, 1.6, ... , 19.4, 19.6, 19.8])

但如果使用list()方法,如

list(a)

突然变成了

[1.0, 1.2, 1.3999999999999999, 1.5999999999999999, ..., 19.399999999999995, 19.599999999999994, 19.799999999999997]

这是一个巨大的错误。我不是专家,所以我无法确切地知道它是如何发生的。我已经向一个对计算机中数字处理的具体主题非常了解的人展示了这一点,他们告诉我它非常好奇,但是无法立即确定具体问题旁边说

  

嗯,这不是一个真正的错误,因为0.2无法准确表示,但几乎肯定不是故意的!所有情况都是这两种方法不是最后一位兼容的

我搜索互联网但没有取得太大成功,既搜索了这个确切的错误,又使用了从上面的解释中提取的关键字。所以我决定在这里问一下

以前有人偶然发现过这种错误吗?有没有人对导致它的原因有深入的解释?

我在CentOS 6.6机器上的Anaconda环境中使用Python 2.7.9。

编辑:显然,Stack Exchange比我更聪明,并且仅在 之后提出了一个相关问题我写下了整件事 Python - Converting an array to a list causes values to change

2 个答案:

答案 0 :(得分:2)

将数组转换为列表时,没有引入数值错误,这只是浮点值在列表和数组中的表示方式的差异。

调用list(a)表示您获得了NumPy浮点类型(不是Python float对象)的列表。打印时,shell会打印浮点值的更多数字。默认情况下,NumPy数组只打印浮点数的1位小数。

如果您将NumPy数组的精度设置得更高,您将看到与列表中相同的值:

>>> np.set_printoptions(precision=16)
>>> a = np.arange(1, 20, 0.2)
>>> a[:10]
array([ 1.                ,  1.2               ,  1.3999999999999999,
        1.5999999999999999,  1.7999999999999998,  1.9999999999999998,
        2.1999999999999997,  2.3999999999999995,  2.5999999999999996,
        2.7999999999999998])

>>> list(a[:10])
[1.0,
 1.2,
 1.3999999999999999,
 1.5999999999999999,
 1.7999999999999998,
 1.9999999999999998,
 2.1999999999999997,
 2.3999999999999995,
 2.5999999999999996,
 2.7999999999999998]

a.tolist()类似的故事。这里,NumPy float数据类型转换为列表的Python float对象(float对象在内部只是C双打,如NumPy)。两种类型都将值近似为相同的精度,并具有相同的表示怪癖。

顺便提一下,值得一提linspace来生成这些类型的范围。您仍会在浮动表示中看到“不准确”,但与arange不同,您可以确定此函数完全返回端点:

>>> np.linspace(1, 20, 96)
array([  1.                ,   1.2               ,   1.3999999999999999,
         1.6000000000000001,   1.8               ,   2.                ,
         ...
         19.                ,  19.1999999999999993,  19.4000000000000021,
         19.6000000000000014,  19.8000000000000007,  20.                ])

答案 1 :(得分:1)

如果使用repr打印数组的各个内容,您将看到完全相同的输出:

import numpy

a = numpy.arange(1, 20, 0.2)

print(repr(a[2]))
1.3999999999999999

或者使用ipython shell:

n [2]: a = numpy.arange(1, 20, 0.2)

In [3]: a[3]
Out[3]: 1.5999999999999999

In [4]: a[2]
Out[4]: 1.3999999999999999

In [5]: a[4]
Out[5]: 1.7999999999999998

python列表显示存储在列表中的对象的repr表示,numpy like python格式化输出到一定的精度。