Принудительное поведение numpy.sum при добавлении нулей

Я понимаю, как математически эквивалентные арифметические операции могут приводить к различным результатам из-за численных ошибок (например, суммирование поплавков в разных порядках).

Однако меня удивляет, что добавление нулей в sum может изменить результат. Я думал, что это всегда верно для float, независимо от того, что: x + 0. == x .

Вот пример. Я ожидал, что все линии будут равны нулю. Может кто-нибудь объяснить, почему это происходит?

 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 

По-видимому, это не происходит при меньших значениях M и Z

Я также убедился, что a.dtype==b.dtype .

Вот еще один пример, который также демонстрирует, что встроенная sum python ведет себя как ожидалось:

 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 

Я использую numpy V1.9.2.

  • Имя не определено в понимании списка с несколькими циклами
  • Лучший способ интегрировать код Python с HTML
  • WxPython: PyInstaller не работает с Нет модуля с именем _core_
  • Python считывает из подпроцесса stdout и stderr отдельно при сохранении порядка
  • Как требовать входа в Django Generic Views?
  • как получить полное содержимое узла с помощью xpath & lxml?
  • Python - проверить, являются ли последние символы в строке номерами
  • Как записать данные в Redshift, что является результатом данных, созданных в Python?
  • One Solution collect form web for “Принудительное поведение numpy.sum при добавлении нулей”

    Короткий ответ: вы видите разницу между

     a + b + c + d 

    а также

     (a + b) + (c + d) 

    которые из-за неточностей с плавающей запятой не совпадают.

    Длинный ответ: Numpy реализует парное суммирование как оптимизацию как скорости (это позволяет упростить векторизации), так и ошибки округления.

    Здесь можно найти реализацию суммы numpy (функция pairwise_sum_@TYPE@ ). Он по существу делает следующее:

    1. Если длина массива меньше 8, выполняется регулярное суммирование по петле. Вот почему странный результат не наблюдается, если W < 4 в вашем случае – в обоих случаях будет использоваться одно и то же для петлевого суммирования.
    2. Если длина составляет от 8 до 128, она накапливает суммы в 8 бит r[0]-r[7] затем суммирует их на ((r[0] + r[1]) + (r[2] + r[3])) + ((r[4] + r[5]) + (r[6] + r[7])) .
    3. В противном случае он рекурсивно суммирует две половины массива.

    Поэтому в первом случае вы получаете a.sum() = a[0] + a[1] + a[2] + a[3] а во втором случае b.sum() = (a[0] + a[1]) + (a[2] + a[3]) что приводит к a.sum() - b.sum() != 0 .

    Python - лучший язык программирования в мире.