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) может решить проблему.