python - functions - Comportamiento numpy.sum extraño al agregar ceros
numpy python tutorial (1)
Respuesta corta: Usted está viendo la diferencia entre
a + b + c + d
y
(a + b) + (c + d)
que debido a las inexactitudes de punto flotante no es lo mismo.
Respuesta larga: Numpy implementa la suma por pares como una optimización de la velocidad (permite una vectorización más fácil) y el error de redondeo.
La implementación de suma de números se puede encontrar here (función pairwise_sum_@TYPE@
). Esencialmente hace lo siguiente:
- Si la longitud de la matriz es menor que 8, se realiza una suma regular de bucles for. Esta es la razón por la que no se observa el resultado extraño si
W < 4
en su caso: en ambos casos se utilizará la misma suma de bucle for. - Si la longitud está entre 8 y 128, acumula las sumas en 8 contenedores
r[0]-r[7]
luego las suma mediante((r[0] + r[1]) + (r[2] + r[3])) + ((r[4] + r[5]) + (r[6] + r[7]))
. - De lo contrario, recursivamente suma dos mitades de la matriz.
Por lo tanto, en el primer caso obtiene a.sum() = a[0] + a[1] + a[2] + a[3]
y en el segundo caso b.sum() = (a[0] + a[1]) + (a[2] + a[3])
que conduce a a.sum() - b.sum() != 0
.
Entiendo cómo las operaciones aritménicas matemáticamente equivalentes pueden resultar en resultados diferentes debido a errores numéricos (por ejemplo, sumar flotadores en diferentes órdenes).
Sin embargo, me sorprende que agregar ceros a la sum
puede cambiar el resultado. Pensé que esto siempre es válido para flotadores, sin importar qué: x + 0. == x
.
Aquí hay un ejemplo. Esperaba que todas las líneas fueran exactamente cero. ¿Alguien puede explicar por qué sucede esto?
M = 4 # number of random values
Z = 4 # number of additional zeros
for i in range(20):
a = np.random.rand(M)
b = np.zeros(M+Z)
b[:M] = a
print a.sum() - b.sum()
-4.4408920985e-16
0.0
0.0
0.0
4.4408920985e-16
0.0
-4.4408920985e-16
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
2.22044604925e-16
0.0
4.4408920985e-16
4.4408920985e-16
0.0
Parece que no sucede con valores más pequeños de M
y Z
También me aseguré de que a.dtype==b.dtype
.
Aquí hay un ejemplo más, que también demuestra que la sum
integrada de python se comporta como se espera:
a = np.array([0.1, 1.0/3, 1.0/7, 1.0/13, 1.0/23])
b = np.array([0.1, 0.0, 1.0/3, 0.0, 1.0/7, 0.0, 1.0/13, 1.0/23])
print a.sum() - b.sum()
=> -1.11022302463e-16
print sum(a) - sum(b)
=> 0.0
Estoy usando numpy V1.9.2.