Почему parseInt (1/0, 19) возвращает 18?

853

У меня есть раздражающая проблема в JavaScript .

> parseInt(1 / 0, 19)
> 18

Почему parseIntфункция возвращает 18?

cebor
источник
3
Интересно. Но почему это раздражает вас? Вы должны обращаться с Бесконечностью другими способами? Если так, то ifможет помочь.
Тило
254
Что, черт возьми, ты вообще делал, что требовало от тебя работы с числами из 19 или ИЛИ делением на ноль !?
Джек М
19
Когда вы запутаетесь в JS, просто вернитесь к этой цитате и помните, что весь этот чертов язык был разработан и реализован менее чем за 10 дней (в зависимости от того, кто это сделал).
Тайлер
32
Из часто задаваемых вопросов: «Вы должны задавать только практические, отвечающие на вопросы вопросы, основанные на реальных проблемах, с которыми вы сталкиваетесь». На самом деле это не "досадная проблема", с которой вы сталкиваетесь, это нереальный пример, который витает в интернете вечно .
Джереми Бэнкс
2
Python делает то же самое: int ('I', 19) == 18
Оберхамси

Ответы:

1292

Результатом 1/0является Infinity.

parseIntобрабатывает свой первый аргумент как строку, что означает, что в первую очередь Infinity.toString()вызывается, создавая строку "Infinity". Так что он работает так же, как если бы вы попросили его преобразовать "Infinity"в основание 19 в десятичную.

Вот цифры в базе 19 вместе с их десятичными значениями:

Base 19   Base 10 (decimal)
---------------------------
   0            0
   1            1
   2            2
   3            3
   4            4
   5            5
   6            6
   7            7
   8            8
   9            9
   a            10
   b            11
   c            12
   d            13
   e            14
   f            15
   g            16
   h            17
   i            18

Что происходит дальше, так это parseInt сканирование входных данных, "Infinity"чтобы найти, какая его часть может быть проанализирована, и останавливается после принятия первого I(поскольку nв базе 19 недопустимая цифра).

Поэтому он ведет себя так, как если бы вы звонили parseInt("I", 19), что преобразуется в десятичную 18 по таблице выше.

Джон
источник
32
@mithunsatheesh Попробуй parseInt('Infini',24).
Supr
112
@mithunsatheesh: Потому что в базе 24 nтоже допустимая цифра, так что на самом деле это заканчивается parseInt("Infini", 24).
Джон
36
Почему кто-то хочет «программировать» на языке, который ведет себя так, мне не понятно.
Франс Боума
45
@FransBouma: JS красива по-своему. И действительно, никакая часть того, что происходит здесь, не является необоснованной в динамическом языке.
Джон
59
@Jon: этот артефакт не является результатом динамического языка; это результат неудачного набора текста. В строго типизированном динамическом языке неявное преобразование Infinity (float) в «Infinity» (string) не должно происходить, чтобы предотвратить такую ​​глупость.
Ли Райан
225

Вот последовательность событий:

  • 1/0 оценивает Infinity
  • parseIntчитает Infinityи радостно отмечает, что I18 в базе 19
  • parseInt игнорирует остаток строки, так как он не может быть преобразован.

Обратите внимание, что вы получите результат для любой базы >= 19, но не для баз ниже этой. Для баз >= 24вы получите больший результат, который nстанет действительной цифрой в этой точке.

Крейг Ситро
источник
@Thilo Кстати, что может быть причиной, почему он может остановиться на 19, если база больше? Вы знаете, какую самую большую базу может интерпретировать JS?
Арнтор
4
@Nordvind Самая большая база parseIntбудет принимать 36, поскольку в английском алфавите 26 букв, и принято использовать цифры, а не буквы как набор действительных цифр в данной базе.
Крейг Ситро
4
Что касается пункта № 2, могу ли я предложить изменить его Infinityна "Infinity"...
CJBS
38

Чтобы добавить к ответам выше:

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

var num = 1 / 0;
var numInBase19 = num.toString(19); // returns the string "Infinity"
kybernetikos
источник
13

Добавить к ответам выше

parseInt(1/0,19) эквивалентно parseInt("Infinity",19)

В пределах базы 19 номеров 0-9и A-I (or a-i)являются действительными номерами. Таким образом, из «Бесконечности» он берет Iбазу 19 и преобразует в базу 10, которая становится 18. Затем он пытается взять следующий символ, т.е.n которого нет в базе 19, поэтому отбрасывает следующие символы (согласно поведению javascript преобразования строки в число )

Так что , если вы пишете parseInt("Infinity",19)или parseInt("I",19)OR parseInt("i",19)результат будет таким же , то есть 18.

Теперь, если вы напишите parseInt("I0",19)результат будет 342 как I X 19 (the base)^1 + 0 X 19^0 = 18 X 19^1 + 0 X 19^0= 18 X 19 + 0 X 1 =342

Точно так же parseInt("I11",19)приведет к6518

т.е.

  18 X 19^2  +   1 X 19^1   +  1 X 19^0
= 18 X 19^2  +   1 X 19^1   +  1 X 19^0
= 18 X 361   +   1 X 19     +  1 X 1
= 6498  +  19  +  1
= 6518
Имдад
источник