Разная математика в разных js-движках
Том МакРайт — разработчик Mapbox и OpenStreetMap — недавно опубликовал статью про отличия реализаций математических функций в JavaScript-движках — "Math keeps changing".
Однажды Том столкнулся с падающими тестами в своей библиотеке для работы со статистическими функциями. Тесты падали в 12-ой версии Node, в 10-ой всё было ок. Его это заинтересовало, и он пошёл смотреть реализации движков и читать спецификацию.
В спецификации ECMAScript сказано, что в ней нет точного описания поведения математических функций (sin, cos, exp, pow, random, sqrt и т,п,). Разработчики стандарта пошли на такой шаг, чтобы в JavaScript-движках можно было использовать все преимущества нижележащей платформы, например, специфичные команды CPU для работы с тригонометрией. Именно из-за этого падали тесты Тома. Исторически V8 использовал свою собственную библиотеку для математических функций, затем использовал JavaScript-порт fdblibm, сейчас там используется C-версия fdblibm.
Для того чтобы предотвратить подобные ошибки, результат вычислений сравнивают относительно малой величины "эпсилон" — Math.abs(result - expected) < epsilon
. Можно также использовать функции из библиотеки stdlib-js, но они работают не так быстро как их соседи из библиотек, скомилированных в нативный код.
В общем, мне статья очень понравилась. Рекомендую почитать.