Czytam to, ale mylę to, co napisano w parseInt z rozdziałem o argumentach radix
Dlaczego to parseInt(8, 3)
→ NaN
i parseInt(16, 3)
→ 1
?
AFAIK 8 i 16 nie są bazowe-3 cyfry, to parseInt(16, 3)
należy zwrócić NaN
zbyt
Czytam to, ale mylę to, co napisano w parseInt z rozdziałem o argumentach radix
Dlaczego to parseInt(8, 3)
→ NaN
i parseInt(16, 3)
→ 1
?
AFAIK 8 i 16 nie są bazowe-3 cyfry, to parseInt(16, 3)
należy zwrócić NaN
zbyt
Odpowiedzi:
Ludzie ciągle się potykają, nawet jeśli wiedzą o tym. :-) Widzisz to z tego samego powodu parseInt("1abc")
zwraca 1: parseInt
zatrzymuje 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ę 8
na ciąg; szczegóły w specyfikacji ). Ale podstawy 3, numery jednocyfrowe to tylko 0
, 1
i 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, 6
ponieważ 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
; x
jest ignorowany. Obsługuje opcjonalny argument podstawa (podstawa liczbowa), więc parseInt("15", 16)
jest 21
( 15
w 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ę 0
na ósemkowe; takie zachowanie nigdy nie zostało określone i zostało wyraźnie zabronione w specyfikacji ES5.) Zwraca, NaN
jeś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 x
są ignorowane). Ponieważ obsługiwana jest tylko liczba dziesiętna, parseFloat("0x15")
jest 0
(ponieważ parsowanie kończy się na x
). Zwraca, NaN
jeś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; 0x
przedrostek = szesnastkowy; 0o
przedrostek = ósemkowy [ES2015 +]; niektóre implementacje go rozszerzają traktować wiodące 0
jako ósemkowe, ale nie w trybie ścisłym). +"10x"
to NaN
dlatego, ż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
+""
0
NaN
Number(str)
- Dokładnie jak niejawna konwersja (np. Jak unary +
powyżej), ale wolniej w niektórych implementacjach. (Nie żeby to miało znaczenie.)
parseInt
po raz pierwszy używa toString
pierwszego argumentu? To miałoby sens.
parseInt
algorytmu: ecma-international.org/ecma-262/7.0/…
123e-2
daje, 1
ponieważ 1.23
najpierw zmienia się w , a następnie parsowanie zatrzymuje się w miejscu dziesiętnym?
NumberFormatException
każdym razem.
parseInt
(wymuszanie pierwszego argumentu na łańcuch) ma sens. Celem parseInt
jest 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 , parseInt
pobiera ciąg. I
Jeśli ciąg nie jest ciągiem, jest on konwertowany na ciąg
Tak więc 16
, 8
lub '1foobar'
jest najpierw konwertowany na ciąg.
Następnie
Jeśli
parseInt
napotka znak, który nie jest liczbą w podanej podstawce, ignoruje go i wszystkie kolejne znaki
Oznacza to, że konwertuje tam, gdzie może. 6
, 8
I foobar
są ignorowane, a tylko to, co jest przed przekształca. Jeśli nic nie ma, NaN
jest 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