Рубрики
Без рубрики

Я нашел ошибку в операторе V8’s Exponentiation

Christoph Christoph Michel I обнаружил ошибку в Exponentiation Exponentiation Ritchie Ritchie Valens на Unsplashi всегда думал, что новый оператор ES6 Exponentiation X ** Y был таким же, как Math.pow (x, y). Действительно, это то, что спецификация говорит о math.pow: вернуть результат применения

Автор оригинала: FreeCodeCamp Community Member.

Кристоф Мишель

Я всегда думал, что новый оператор ES6 Exponentiation x ** y был таким же, как Math.pow (x, y) Отказ

Действительно, это то, что Спецификация говорит о Математика :

12.6.4 – Применение ** Оператор утверждает, что результат является Зависимый от внедрения – Но все равно не должно быть несоответствие между ** и Math.pow Отказ

Однако, оценивая следующее в текущем движке V8 JS (Chrome/Node) в этом:

console.log('1.35 ** 92', 1.35 ** 92)                   // 978828715394.7672console.log('Math.pow(1.35, 92)', Math.pow(1.35, 92))   // 978828715394.767

Оператор Exponentiation ** Возвращает более точное приближение.

Но это не единственная странная странность с оператором Exponentiation: давайте попробуем оценить то же самое с переменными ( repl ) – это не должно иметь никакого значения:

const exponent = 92;console.log(`1.35 ** exponent`, 1.35 ** exponent)                   // 978828715394.767console.log('1.35 ** 92', 1.35 ** 92)                               // 978828715394.7672console.log(`Math.pow(1.35, exponent)`, Math.pow(1.35, exponent))   // 978828715394.767console.log('Math.pow(1.35, 92)', Math.pow(1.35, 92))               // 978828715394.767

Но это делает: 1.35 ** 92 отличается от 1.35 ** экспонент Отказ

Так что, кажется, здесь происходит, что компилятор обрабатывает код JS 1.35 ** 92 который уже постоянный сложенный

Это имеет смысл, так как V8 действительно компилирует машинный код.

V8 увеличивает производительность, составив JavaScript на родной машинный код перед его выполнением, по сравнению с выполнением Bytecode или интерпретации его.

V8 работает, сначала интерпретируя код JS со своими Переводчик зажигания. Это делает второй пробег с Turbofan Compiler Оптимизация .. Машинный код Отказ

Турбофан сейчас делает постоянная складная. Его алгоритм Exponentiation имеет лучшую точность, чем алгоритм Exponentiation jit Compiler (зажигание).

Если вы попробуете то же самое в других двигателях JS, как Firefox’s Spidermonkey. Результатом является последовательное значение 978828715394.767 Среди всех вычислений.

Это ошибка?

Я бы так сказал, хотя это не было серьезным в моем коде. Но это все еще не следит за спецификацией, который говорит Математика и ** должен привести к тому же величине.

Если вы транспилите код с Babel, x ** y переводится на Math.pow (x, y) , который снова приводит к расхождениям между транспортированным и непереданным кодом. Как мы видели, Math.pow (1.35, 92) это не Быть оптимизированным (только операторы кажутся оптимизированными V8). Поэтому 1.35 ** 92 Результаты в разном коде, когда транспортирован до ES5 Отказ

Используя эту ошибку и игнорируя любые практики чистого кода, мы можем написать приятную функцию, чтобы определить, запускаем ли мы на Chrome (если вы не транспортируете свой код?):

function isChrome() {    return 1.35 ** 92 !== Math.pow(1.35, 92)}

Все еще более читаемый, чем строки агента пользователя. ?

Первоначально опубликовано в cmichel.io

Оригинал: “https://www.freecodecamp.org/news/i-found-a-bug-in-v8s-exponentiation-operator-dcddfa5b8482/”