将 NumPy 数组转换为列表时浮点不一致

use*_*703 2 python arrays floating-point numpy list

我有一个由 py​​thon numpy 生成的区间范围。这些值符合预期,但是当数组转换为列表时,这些值与数组中的值不同。

numpy.linspace(0.3,0.7,5)
array([ 0.3,  0.4,  0.5,  0.6,  0.7])

numpy.linspace(0.3,0.7,5).tolist()
[0.3, 0.39999999999999997, 0.5, 0.6, 0.7]

list(numpy.linspace(0.3,0.7,5))
 [0.29999999999999999,0.39999999999999997,0.5,0.59999999999999998,
 0.69999999999999996]
Run Code Online (Sandbox Code Playgroud)

为什么 numpy 会有这样的行为?无论如何,是否可以使列表中的值与数组相同,而不使用另一个循环来舍入列表中的值?

cs9*_*s95 5

这恰好是因为数据类型和__repr__每种类型相应的实现:

l = numpy.linspace(0.3,0.7,5).tolist()

[type(x)  for x in l]
[float, float, float, float, float]
Run Code Online (Sandbox Code Playgroud)

第一种情况,tolist将每个np.float对象转换为Pythonfloat对象,其__repr__实现根据盖伊算法自动截断浮点数。奥托:

l = list(numpy.linspace(0.3,0.7,5))

[type(x)  for x in l]
[numpy.float64, numpy.float64, numpy.float64, numpy.float64, numpy.float64]
Run Code Online (Sandbox Code Playgroud)

list仅在数组周围调用 a不会将列表元素转换为 a float,而是保留其原始np.float类型,它们具有不同的表示形式。请记住,第二种情况下的浮点表示是它们在内存中的实际表示方式:

import decimal

decimal.Decimal(0.3)
Decimal('0.299999999999999988897769753748434595763683319091796875')
Run Code Online (Sandbox Code Playgroud)

因为许多浮点数没有精确的位表示。看看我们心爱的规范浮点数​​学坏了吗?更多细节。