Арифметика Python vs Javascript с плавающей точкой дает очень разные ответы. Что я делаю не так?

версия Python | Javascript версия | Технический документ

Итак, я работаю над сайтом, чтобы рассчитать рейтинги Glicko для двух игровых игр. Он включает в себя много арифметики с плавающей запятой (квадратные корни, показатели, деление, все неприятные вещи), и я почему-то получаю совершенно другой ответ от реализации Python алгоритма, который я переводил по строке. Версия Python дает в основном ожидаемый ответ для примера, найденного в исходном документе, описывающем алгоритм, но версия Javascript довольно немного выключена.

Я сделал ошибку в переводе или математику с плавающей запятой Javascript просто менее точную?

Expected answer: [1464, 151.4]
Python answer: [1462, 155.5]
Javascript answer: [1470.8, 89.7]

Таким образом, расчет рейтинга не так плох, будучи точным 99,6%, но дисперсия отключена на 2/3!

Изменить: люди указали, что значение по умолчанию для RD в версии Pyglicko равно 200. Это случай, когда исходный разработчик уходит в тестовый код, на который я верю, поскольку тестовый пример выполняется для человека с RD 200, но, очевидно, значение по умолчанию должно быть 350. Однако я указал 200 в моем тестовом примере в Javascript, так что это не проблема.

Изменить: Изменен алгоритм использования карты/уменьшения. Рейтинг менее точный, дисперсия более точная, как по какой-либо заметной причине. Начинается наступление.

Ответ 1

обычно вы получаете такие ошибки, когда вы вычитаете два одинаковых числа - тогда обычно незначительные различия между значениями усиливаются. например, если у вас есть два значения, которые 1.2345 и 1.2346 в python, но 1.2344 и 1.2347 в javascript, то разница составляет 1e-4 и 3 e-4 соответственно (т.е. один из них равен 3 раза).

поэтому я бы посмотрел, где у вас есть вычитания в коде и проверьте эти значения. вы можете обнаружить, что вы можете (1) переписать математику, чтобы избежать вычитания (часто оказывается, что вы можете найти выражение, которое вычисляет разницу каким-либо другим способом) или (2) сосредоточиться на том, почему значения в этой конкретной точке отличаются друг от друга между двумя языками (возможно, разница в pi, что идентифицируемый другой ответ усиливается таким образом).

также возможно, хотя и менее вероятно, что у вас есть разница, потому что что-то рассматривается как целое число в python, но как float в javascript. в python существует разница между целыми числами и float, и если вы не будете осторожны, вы можете делать такие вещи, как разделение двух целых чисел, чтобы получить другое целое число (например, 3/2 = 1 в python). в то время как в javascript все числа "действительно" плавают, поэтому этого не происходит.

Наконец, возможно, существуют небольшие различия в том, как выполняются вычисления. но они "нормальные" - чтобы получить такие радикальные различия, вам нужно что-то вроде того, что я описал выше, чтобы это произошло.

PS: также обратите внимание на то, что Даниэль Баулиг сказал о начальном значении параметра rd в комментариях выше.

Ответ 2

Я предполагаю, что это касается приближений, которые вы используете для некоторых констант в версии JavaScript. Ваш pi2 в частности кажется немного.. кратким. Я считаю, что Python использует удвоения для этих значений.