parseInt() неправильно анализирует числовые литералы с показателем степени

Я только что заметил, что parseInt Функция не заботится о десятичных дробях в случае целых чисел (числа, содержащие e персонаж).

Давайте возьмем пример: -3.67394039744206e-15

> parseInt(-3.67394039744206e-15)
-3
> -3.67394039744206e-15.toFixed(19)
-3.6739e-15
> -3.67394039744206e-15.toFixed(2)
-0
> Math.round(-3.67394039744206e-15)
0

Я ожидал, что parseInt также вернется 0, Что происходит на более низком уровне? Почему parseInt вернуть 3 в этом случае (некоторые фрагменты из исходного кода будут оценены)?

В этом примере я использую node v0.12.1, но я ожидаю, что то же самое произойдет в браузере и других движках JavaScript.

7 ответов

Решение

Я думаю причина в том parseInt преобразует переданное значение в строку, вызывая ToString который вернется "-3.67394039744206e-15", а затем разбирает его так, что он будет учитывать -3 и вернет его.

MDN документация

Функция parseInt преобразует свой первый аргумент в строку, анализирует ее и возвращает целое число или NaN

parseInt(-3.67394039744206e-15) === -3

parseInt Функция ожидает строку в качестве первого аргумента. JavaScript позвонит toString метод за сценой, если аргумент не является строкой. Таким образом, выражение оценивается следующим образом:

(-3.67394039744206e-15).toString()
// "-3.67394039744206e-15"
parseInt("-3.67394039744206e-15")
// -3

-3.67394039744206e-15.toFixed(19) === -3.6739e-15

Это выражение анализируется как:

  • Одинарный - оператор
  • Число буквальное 3.67394039744206e-15
  • .toFixed() - свойство accessor, имя свойства и вызов функции

Способ синтаксического анализа числовых литералов описан здесь. Интересно, что +/- не являются частью буквального числа. Итак, мы имеем:

// property accessor has higher precedence than unary - operator
3.67394039744206e-15.toFixed(19)
// "0.0000000000000036739"
-"0.0000000000000036739"
// -3.6739e-15

Аналогично для -3.67394039744206e-15.toFixed(2):

3.67394039744206e-15.toFixed(2)
// "0.00"
-"0.00"
// -0

Если проанализированная строка (лишенная знака +/-) содержит какой-либо символ, который не является радикальной цифрой (в вашем случае 10), то создается подстрока, содержащая все остальные символы перед тем, как такой символ отбрасывает эти нераспознанные символы.

В случае -3.67394039744206e-15, преобразование начинается, и основание определяется как основание 10 -> преобразование происходит до тех пор, пока не встретится '.' который не является допустимым символом в базе 10 - Таким образом, фактически, преобразование происходит для 3 который дает значение 3, а затем применяется знак, таким образом -3.

Для логики реализации - http://www.ecma-international.org/ecma-262/5.1/

Больше примеров -

alert(parseInt("2711e2", 16));
alert(parseInt("2711e2", 10));

Отметить:

Основа начинается с основания 10.

Если первый символ - "0", он переключается на основание 8.

Если следующий символ - "x", он переключается на основание 16.

Он пытается разобрать строки в целые числа. Я подозреваю, что ваши поплавки сначала приводятся к строкам. Затем, вместо того, чтобы анализировать все значение, а затем округлять, он использует символьную функцию синтаксического анализа и остановится, когда доберется до первой десятичной точки, игнорируя любые десятичные разряды или показатели.

Некоторые примеры здесь http://www.w3schools.com/jsref/jsref_parseint.asp

parseInt имеет целью анализ строки, а не числа:

Функция parseInt() анализирует строковый аргумент и возвращает целое число указанного радиуса (основание в математических системах счисления).

А также parseInt вызывает функцию ToString при этом все нечисловые символы игнорируются.

Ты можешь использовать Math.round, который также анализирует строки и округляет число до ближайшего целого числа:

Math.round("12.2e-2") === 0 //true

Math.round("12.2e-2")может округляться в большую или меньшую сторону в зависимости от значения. Следовательно, могут возникнуть проблемы.

new Number("3.2343e-10").toFixed(0) может решить проблему.

Похоже, вы пытаетесь вычислить с помощью parseFloat, это даст вам правильный ответ.

parseIntкак говорится, возвращает целое число, тогда какparseFloatвозвращает число с плавающей запятой или экспоненциальное число:

      parseInt(-3.67394039744206e-15) = -3
parseFloat(-3.67394039744206e-15) = -3.67394039744206e-15

Другие вопросы по тегам