我不明白为什么将float32-Array转换为float64-Array会显着改变数组的平均值。
import numpy as n
a = n.float32(100. * n.random.random_sample((10000000))+1000.)
b = a.astype(n.float64)
print n.mean(a), a.dtype, a.shape
print n.mean(b), b.dtype, b.shape
结果(应该是大约1050,所以float64是正确的):
1028.346368 float32 (10000000,)
1049.98284473 float64 (10000000,)
答案 0 :(得分:4)
32位浮点数仅精确到约7位有效数字。随着值的总和增加,您开始失去较小数字的准确性。 64位数字大约有13-16个,所以你需要更大的数量才能看到相同的效果。
要在示例中看到此效果,请注意增加数组子集的方法:
>>> for i in [j * 1000000 for j in range(1, 11)]:
... print i, n.mean(a[:i]), n.mean(b[:i])
...
1000000 1050.92768 1049.95339668
2000000 1045.289856 1049.96298122
3000000 1038.47466667 1049.97903538
4000000 1034.856 1049.98635745
5000000 1032.6848512 1049.98521094
6000000 1031.237376 1049.98658562
7000000 1030.20346514 1049.98757511
8000000 1029.428032 1049.98615102
9000000 1028.82497422 1049.98925409
10000000 1028.3424768 1049.98771529
答案 1 :(得分:4)
@bogatron解释了导致精度损失的原因。为了解决这类问题,np.mean
有一个可选的dtype
参数,允许您指定用于内部操作的类型。所以你可以这样做:
>>> np.mean(a)
1028.3446272000001
>>> np.mean(a.astype(np.float64))
1049.9776601123901
>>> np.mean(a, dtype=np.float64)
1049.9776601123901
第三种情况明显快于第二种情况,尽管比第一种情况慢:
In [3]: %timeit np.mean(a)
100 loops, best of 3: 10.9 ms per loop
In [4]: %timeit np.mean(a.astype(np.float64))
10 loops, best of 3: 51 ms per loop
In [5]: %timeit np.mean(a, dtype=np.float64)
100 loops, best of 3: 19.2 ms per loop
答案 2 :(得分:2)
问题在于均值和求和函数的实现。
浮点值具有恒定的精度。当你向一个大的值添加小值时,你会失去小值的精度。
要克服这个问题,你需要划分数组并部分计算总和:
s=n.float32(0)
for p in xrange(0,a.size,1000):
s+= n.sum(a[p:p+1000])
print 'Sum:',s
print 'Mean:',s/a.size
会给你更正确的结果。