Dlaczego parsowanie (1/0, 19) zwraca wartość 18?

853

Mam irytujący problem z JavaScript .

> parseInt(1 / 0, 19)
> 18

Dlaczego parseIntfunkcja powraca 18?

cebor
źródło
3
Ciekawy. Ale dlaczego jest to dla ciebie irytujący problem? Czy musisz obsługiwać Infinity na inne sposoby? Jeśli tak, ifmoże pomóc.
Thilo,
254
Co, u diabła, robiłeś, wymagało to pracy z liczbami podstawowymi 19 lub z podziałem przez zero !?
Jack M
19
Kiedy się zdezorientujesz co do JS, po prostu wróć do tego cytatu i pamiętaj, że cały ten przeklęty język został zaprojektowany i wdrożony w mniej niż 10 dni (według osoby, która to zrobiła).
tylerl
32
Z FAQ: „Powinieneś zadawać tylko praktyczne, możliwe do odpowiedzi pytania oparte na rzeczywistych problemach, z którymi się stykasz”. W rzeczywistości nie jest to „irytujący problem”, ale nierealistyczny przykład, który unosi się w Internecie na zawsze .
Jeremy Banks
2
python robi to samo: int ('I', 19) == 18
oberhamsi

Odpowiedzi:

1292

Rezultatem 1/0jest Infinity.

parseInttraktuje swój pierwszy argument jako ciąg znaków, co oznacza przede wszystkim, że Infinity.toString()jest wywoływany, tworząc ciąg "Infinity". Działa to tak samo, jakbyś poprosił go o konwersję "Infinity"w podstawie 19 na dziesiętną.

Oto cyfry w bazie 19 wraz z ich wartościami dziesiętnymi:

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

To, co dzieje się potem, polega na parseIntskanowaniu danych wejściowych w "Infinity"celu znalezienia, która część może zostać przeanalizowana i zatrzymuje się po zaakceptowaniu pierwszej I(ponieważ nnie jest prawidłową cyfrą w bazie 19).

Dlatego zachowuje się tak, jakbyś zadzwonił parseInt("I", 19), co konwertuje na liczbę dziesiętną według powyższej tabeli.

Jon
źródło
32
@mithunsatheesh Try parseInt('Infini',24).
Supr
112
@mithunsatheesh: Ponieważ w bazie 24 njest również poprawna cyfra, więc tak naprawdę kończy się parseInt("Infini", 24).
Jon
36
Dlaczego ktoś chce „programować” w języku, który zachowuje się w ten sposób, jest poza mną.
Frans Bouma,
45
@FransBouma: JS jest piękny na swój sposób. I tak naprawdę, żadna część tego, co się tu dzieje, nie jest nierozsądna w dynamicznym języku.
Jon
59
@Jon: ten artefakt nie jest wynikiem dynamicznego języka; jest wynikiem luźnego pisania. W języku dynamicznym o ściśle określonym typie domyślna konwersja Infinity (liczba zmiennoprzecinkowa) na „Infinity” (ciąg znaków) nie miałaby miejsca, aby zapobiec tego rodzaju głupstwu.
Lie Ryan,
225

Oto sekwencja wydarzeń:

  • 1/0 ocenia na Infinity
  • parseIntczyta Infinityi szczęśliwie zauważa, że Ima 18 w bazie 19
  • parseInt ignoruje pozostałą część ciągu, ponieważ nie można go przekonwertować.

Zauważ, że uzyskasz wynik dla dowolnej bazy >= 19, ale nie dla baz poniżej. W przypadku zasad >= 24otrzymasz większy wynik, ponieważ nw tym momencie staje się prawidłową cyfrą.

Craig Citro
źródło
@Thilo BTW, jaki byłby powód, dlaczego może zatrzymać się na 19, jeśli baza jest większa? Czy wiesz, jaka jest największa baza, jaką JS może wykonać?
Arnthor,
4
@Nordvind Największa baza parseIntakceptuje 36, ponieważ w alfabecie angielskim jest 26 liter, a konwencja polega na użyciu cyfr, a następnie liter jako zestawu prawidłowych cyfr w danej bazie.
Craig Citro,
4
W punkcie 2, czy mogę zasugerować zmianę Infinityna "Infinity"...
CJBS 4'17
38

Aby dodać do powyższych odpowiedzi:

parseInt jest przeznaczony do parsowania ciągów na liczby (wskazówka znajduje się w nazwie). W twojej sytuacji nie chcesz wcale analizować, ponieważ 1/0 jest już liczbą, więc jest to dziwny wybór funkcji. Jeśli masz numer (który robisz) i chcesz przekonwertować go na określoną bazę, powinieneś użyć toString z podstawką .

var num = 1 / 0;
var numInBase19 = num.toString(19); // returns the string "Infinity"
kybernetikos
źródło
13

Aby dodać do powyższych odpowiedzi

parseInt(1/0,19) jest równa parseInt("Infinity",19)

W obrębie 19 liczb podstawowych 0-9i A-I (or a-i)są prawidłowymi liczbami. Tak więc z „Nieskończoności” pobiera Ibazę 19 i konwertuje na bazę 10, która staje się 18, a następnie próbuje pobrać następny znak, tj. nKtóry nie jest obecny w bazie 19, więc odrzuca kolejne znaki (zgodnie z zachowaniem konwersji kodu javascript na liczbę )

Tak więc, jeśli napiszesz parseInt("Infinity",19)LUB parseInt("I",19)LUB parseInt("i",19)wynik będzie taki sam, tj 18.

Teraz, jeśli piszesz parseInt("I0",19)wynik będzie 342 jak 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

Podobnie parseInt("I11",19)spowoduje6518

to znaczy

  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
Imdad
źródło