Среда программирования Unix Kernighan и Щукой.
[еще 114], чем какая-либо другая книга, это преподавало мне преимущества в создании маленьких, легко протестированных инструментов, которые могут быть объединены, чтобы сделать большие вещи.
Есть еще один однопроходный алгоритм, который немного меняет порядок вычислений. В псевдокод:
n = 0
mean = 0
M2 = 0
for x in data:
n = n + 1
delta = x - mean
mean = mean + delta/n
M2 = M2 + delta*(x - mean) # This expression uses the new value of mean
variance_n = M2/n # Sample variance
variance = M2/(n - 1) # Unbiased estimate of population variance
(Источник: http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance )
Кажется, это лучше работает в отношении проблем, которые вы указали с обычным алгоритмом.
IEEE предоставляет четыре режима округления (в сторону -inf, в сторону + inf, в сторону 0, ближайший). Похоже, вы хотите, чтобы к + inf. В C90 или C ++ нет стандартного элемента управления. C99 добавил заголовок
, который также присутствует как расширение в некоторых реализациях C90 и C ++. Чтобы соответствовать стандарту C99, вам нужно написать что-то вроде:
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int old_round_mode = fegetround();
int set_round_ok = fesetround(FE_UPWARD);
assert(set_round_ok == 0);
...
int set_round_ok = fesetround(old_round_mode);
assert(set_round_ok == 0);
Хорошо известно, что используемый вами алгоритм численно нестабилен и имеет проблемы с точностью. Для обеспечения точности лучше выполнить два прохода данных.
Если вы не беспокоитесь о точности, а только об отрицательной дисперсии, почему бы вам просто не сделать V (x) = Max (0, E (X ^ 2) - E (X) ^ 2)