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
и вернет его.
Функция 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