Ada kekurangan dalam jawaban Jason R, yang dibahas dalam Knuth's "Art of Computer Programming" vol. 2. Masalah muncul jika Anda memiliki standar deviasi yang merupakan sebagian kecil dari rata-rata: perhitungan E (x ^ 2) - (E (x) ^ 2) menderita sensitivitas parah hingga kesalahan pembulatan titik mengambang.
Anda bahkan dapat mencobanya sendiri dalam skrip Python:
ofs = 1e9
A = [ofs+x for x in [1,-1,2,3,0,4.02,5]]
A2 = [x*x for x in A]
(sum(A2)/len(A))-(sum(A)/len(A))**2
Saya mendapatkan -128.0 sebagai jawaban, yang jelas tidak valid secara komputasi, karena matematika memperkirakan bahwa hasilnya harus non-negatif.
Knuth mengutip pendekatan (saya tidak ingat nama penemunya) untuk menghitung rata-rata berjalan dan standar deviasi yang kira-kira seperti ini:
initialize:
m = 0;
S = 0;
n = 0;
for each incoming sample x:
prev_mean = m;
n = n + 1;
m = m + (x-m)/n;
S = S + (x-m)*(x-prev_mean);
dan kemudian setelah setiap langkah, nilai dari m
mean, dan standar deviasi dapat dihitung sebagai sqrt(S/n)
atau sqrt(S/n-1)
tergantung pada definisi favorit Anda tentang standar deviasi.
Persamaan yang saya tulis di atas sedikit berbeda dari yang ada di Knuth, tetapi ini setara secara komputasi.
Ketika saya memiliki beberapa menit lagi, saya akan memberi kode rumus di atas dalam Python dan menunjukkan bahwa Anda akan mendapatkan jawaban yang tidak negatif (yang diharapkan dekat dengan nilai yang benar).
pembaruan: ini dia.
test1.py:
import math
def stats(x):
n = 0
S = 0.0
m = 0.0
for x_i in x:
n = n + 1
m_prev = m
m = m + (x_i - m) / n
S = S + (x_i - m) * (x_i - m_prev)
return {'mean': m, 'variance': S/n}
def naive_stats(x):
S1 = sum(x)
n = len(x)
S2 = sum([x_i**2 for x_i in x])
return {'mean': S1/n, 'variance': (S2/n - (S1/n)**2) }
x1 = [1,-1,2,3,0,4.02,5]
x2 = [x+1e9 for x in x1]
print "naive_stats:"
print naive_stats(x1)
print naive_stats(x2)
print "stats:"
print stats(x1)
print stats(x2)
hasil:
naive_stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571427}
{'variance': -128.0, 'mean': 1000000002.0028572}
stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571431}
{'variance': 4.0114775868357446, 'mean': 1000000002.0028571}
Anda akan mencatat bahwa masih ada beberapa kesalahan pembulatan, tetapi itu tidak buruk, sedangkan naive_stats
hanya muntah.
sunting: Hanya memperhatikan komentar Belisarius yang mengutip Wikipedia yang menyebutkan algoritma Knuth.