Во-первых, я не математик, поэтому точность большого числа редко попадает в мою повседневную работу. Пожалуйста, будьте нежны. ;)
Использование NumPy для генерации матрицы со значениями, равными 1:
>>> m = numpy.matrix([(1.0 / 1000) for x in xrange(1000)]).T
>>> m
matrix[[ 0.001 ],
[ 0.001 ],
...
[ 0.001 ]])
В 64-битной Windows с Python 2.6 суммирование редко получается до 1,0. math.fsum () работает с этой матрицей, но если я изменяю матрицу для использования меньших чисел, этого не происходит.
>>> numpy.sum(m)
1.0000000000000007
>>> math.fsum(m)
1.0
>>> sum(m)
matrix([[ 1.]])
>>> float(sum(m))
1.0000000000000007
В 32-битном Linux (Ubuntu) с Python 2.6 суммирование всегда получается до 1,0.
>>> numpy.sum(m)
1.0
>>> math.fsum(m)
1.0
>>> sum(m)
matrix([[ 1.]])
>>> float(sum(m))
1.0000000000000007
Я могу добавить эпсилон к своему коду при оценке, если сумма матрицы равна 1 (например, -epsilon <сумма (м) <+ epsilon), но сначала я хочу понять, в чем причина различий в Python, и если есть лучший способ правильно определить сумму. </p>
Насколько я понимаю, сумма (-ы) обрабатывают машинное представление чисел (чисел с плавающей запятой) иначе, чем их отображение, и при суммировании используется внутреннее представление. Однако, глядя на 3 метода, которые я использовал для расчета суммы, не ясно, почему они все разные или одинаковые между платформами.
Какой лучший способ правильно рассчитать сумму матрицы?
Если вы ищете более интересную матрицу, это простое изменение будет иметь меньшие номера матрицы:
>>> m = numpy.matrix([(1.0 / 999) for x in xrange(999)]).T
Заранее спасибо за любую помощь!
Update
Я думаю, что я что-то понял. Если я исправлю значение, хранящееся в 32-битной переменной, результаты будут соответствовать 32-битной сумме в Linux.
>>> m = numpy.matrix([(numpy.float32(1.0) / 1000) for x in xrange(1000)]).T
>>> m
matrix[[ 0.001 ],
[ 0.001 ],
...
[ 0.001 ]])
>>> numpy.sum(m)
1.0
Это установит, что номера машин матрицы будут представлять 32-разрядные числа с плавающей запятой, а не 64-разрядные в моем тесте Windows, и будут суммироваться правильно. Почему число с плавающей запятой 0,001 не равно номеру машины в 32-разрядной и 64-разрядной системах? Я ожидал бы, что они будут другими, если я пытаюсь хранить очень маленькие числа с большим количеством десятичных знаков.
У кого-нибудь есть мысли по этому поводу? Должен ли я в этом случае явно переключаться на 32-разрядные числа с плавающей запятой, или существует 64-разрядный метод суммирования? Или я вернулся к добавлению эпсилона? Извините, если я звучу глупо, мне интересны мнения. Спасибо!