Czytam to, ale mylę to, co napisano w parseInt z rozdziałem o argumentach radix
Dlaczego to parseInt(8, 3)→ NaNi parseInt(16, 3)→ 1?
AFAIK 8 i 16 nie są bazowe-3 cyfry, to parseInt(16, 3)należy zwrócić NaNzbyt
Czytam to, ale mylę to, co napisano w parseInt z rozdziałem o argumentach radix
Dlaczego to parseInt(8, 3)→ NaNi parseInt(16, 3)→ 1?
AFAIK 8 i 16 nie są bazowe-3 cyfry, to parseInt(16, 3)należy zwrócić NaNzbyt
Odpowiedzi:
Ludzie ciągle się potykają, nawet jeśli wiedzą o tym. :-) Widzisz to z tego samego powodu parseInt("1abc")zwraca 1: parseIntzatrzymuje się na pierwszym nieprawidłowym znaku i zwraca cokolwiek ma w tym momencie. Jeśli nie ma poprawnych znaków do przeanalizowania, zwraca NaN.
parseInt(8, 3)oznacza „parsuj "8"w bazie 3” (zwróć uwagę, że konwertuje liczbę 8na ciąg; szczegóły w specyfikacji ). Ale podstawy 3, numery jednocyfrowe to tylko 0, 1i 2. To tak, jakby poprosić go o parsowanie "9"ósemkowe. Ponieważ nie było żadnych ważnych znaków, masz NaN.
parseInt(16, 3)prosi go o parsowanie "16"w bazie 3. Ponieważ może on parsować 1, robi, a następnie zatrzymuje się na, 6ponieważ nie może go parsować. Więc wraca 1.
Ponieważ pytanie to zyskuje wiele uwagi i może zajmować wysokie pozycje w wynikach wyszukiwania, oto przegląd opcji konwersji ciągów znaków na liczby w JavaScript, z ich różnymi osobliwościami i aplikacjami (przeniesionymi z innej mojej odpowiedzi tutaj na SO):
parseInt(str[, radix])- Konwertuje jak najwięcej początku ciągu na liczbę całkowitą (całkowitą), ignorując dodatkowe znaki na końcu. Tak parseInt("10x")jest 10; xjest ignorowany. Obsługuje opcjonalny argument podstawa (podstawa liczbowa), więc parseInt("15", 16)jest 21( 15w systemie szesnastkowym). Jeśli nie ma podstawki, przyjmuje liczbę dziesiętną, chyba że ciąg zaczyna się od 0x(lub 0X), w którym to przypadku pomija je i przyjmuje wartość szesnastkową. (Niektóre przeglądarki traktowały ciągi zaczynające się 0na ósemkowe; takie zachowanie nigdy nie zostało określone i zostało wyraźnie zabronione w specyfikacji ES5.) Zwraca, NaNjeśli nie można znaleźć analizowalnych cyfr.
parseFloat(str)- Podobnie jak parseInt, ale robi liczby zmiennoprzecinkowe i obsługuje tylko dziesiętne. Ponownie dodatkowe znaki na łańcuchu są ignorowane, więc parseFloat("10.5x")jest 10.5(the xsą ignorowane). Ponieważ obsługiwana jest tylko liczba dziesiętna, parseFloat("0x15")jest 0(ponieważ parsowanie kończy się na x). Zwraca, NaNjeśli nie można znaleźć analizowalnych cyfr.
Unary +, np. +str- (np. Niejawna konwersja) Konwertuje cały ciąg na liczbę przy użyciu liczb zmiennoprzecinkowych i standardowej notacji liczb JavaScript (tylko cyfry i kropka dziesiętna = dziesiętna; 0xprzedrostek = szesnastkowy; 0oprzedrostek = ósemkowy [ES2015 +]; niektóre implementacje go rozszerzają traktować wiodące 0jako ósemkowe, ale nie w trybie ścisłym). +"10x"to NaNdlatego, że niex jest ignorowane. jest , jest , jest , jest [ES2015 +]. Ma hascha: nie jest , jak można się spodziewać.+"10"10+"10.5"10.5+"0x15"21+"0o10"8+""0NaN
Number(str)- Dokładnie jak niejawna konwersja (np. Jak unary +powyżej), ale wolniej w niektórych implementacjach. (Nie żeby to miało znaczenie.)
parseIntpo raz pierwszy używa toStringpierwszego argumentu? To miałoby sens.
parseIntalgorytmu: ecma-international.org/ecma-262/7.0/…
123e-2daje, 1ponieważ 1.23najpierw zmienia się w , a następnie parsowanie zatrzymuje się w miejscu dziesiętnym?
NumberFormatExceptionkażdym razem.
parseInt(wymuszanie pierwszego argumentu na łańcuch) ma sens. Celem parseIntjest parsowanie łańcucha na liczbę całkowitą. Więc jeśli dasz mu coś, co nie jest łańcuchem, sensowne jest uzyskanie jego reprezentacji na początku. To, co potem robi , to cała „inna historia…
Z tego samego powodu, który
>> parseInt('1foobar',3)
<- 1
W doc , parseIntpobiera ciąg. I
Jeśli ciąg nie jest ciągiem, jest on konwertowany na ciąg
Tak więc 16, 8lub '1foobar'jest najpierw konwertowany na ciąg.
Następnie
Jeśli
parseIntnapotka znak, który nie jest liczbą w podanej podstawce, ignoruje go i wszystkie kolejne znaki
Oznacza to, że konwertuje tam, gdzie może. 6, 8I foobarsą ignorowane, a tylko to, co jest przed przekształca. Jeśli nic nie ma, NaNjest zwracane.
/***** Radix 3: Allowed numbers are [0,1,2] ********/
parseInt(4, 3); // NaN - We can't represent 4 using radix 3 [allowed - 0,1,2]
parseInt(3, 3); // NaN - We can't represent 3 using radix 3 [allowed - 0,1,2]
parseInt(2, 3); // 2 - yes we can !
parseInt(8, 3); // NaN - We can't represent 8 using radix 3 [allowed - 0,1,2]
parseInt(16, 3); // 1
//'16' => '1' (6 ignored because it not in [0,1,2])
/***** Radix 16: Allowed numbers/characters are [0-9,A-F] *****/
parseInt('FOX9', 16); // 15
//'FOX9' => 'F' => 15 (decimal value of 'F')
// all characters from 'O' to end will be ignored once it encounters the out of range'O'
// 'O' it is NOT in [0-9,A-F]
Kilka innych przykładów:
parseInt('45', 13); // 57
// both 4 and 5 are allowed in Radix is 13 [0-9,A-C]
parseInt('1011', 2); // 11 (decimal NOT binary)
parseInt(7,8); // 7
// '7' => 7 in radix 8 [0 - 7]
parseInt(786,8); // 7
// '78' => '7' => 7 (8 & next any numbers are ignored bcos 8 is NOT in [0-7])
parseInt(76,8); // 62
// Both 7 & 6 are allowed '76' base 8 decimal conversion is 62 base 10