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.

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

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

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

Другие примеры -

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

Ответ 4

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

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

Ответ 5

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

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

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

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

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

Ответ 6

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

новый номер ("3.2343e-10"). toFixed (0) может решить проблему.