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
javascript
numbers
parseint
radix
Devid Farinelli
źródło
źródło
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, zwracaNaN
.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 tylko0
,1
i2
. To tak, jakby poprosić go o parsowanie"9"
ósemkowe. Ponieważ nie było żadnych ważnych znaków, maszNaN
.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 wraca1
.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. TakparseInt("10x")
jest10
;x
jest ignorowany. Obsługuje opcjonalny argument podstawa (podstawa liczbowa), więcparseInt("15", 16)
jest21
(15
w systemie szesnastkowym). Jeśli nie ma podstawki, przyjmuje liczbę dziesiętną, chyba że ciąg zaczyna się od0x
(lub0X
), 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 jakparseInt
, ale robi liczby zmiennoprzecinkowe i obsługuje tylko dziesiętne. Ponownie dodatkowe znaki na łańcuchu są ignorowane, więcparseFloat("10.5x")
jest10.5
(thex
są ignorowane). Ponieważ obsługiwana jest tylko liczba dziesiętna,parseFloat("0x15")
jest0
(ponieważ parsowanie kończy się nax
). 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ące0
jako ósemkowe, ale nie w trybie ścisłym).+"10x"
toNaN
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.)źródło
parseInt
po raz pierwszy używatoString
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. CelemparseInt
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
W doc ,
parseInt
pobiera ciąg. ITak więc
16
,8
lub'1foobar'
jest najpierw konwertowany na ciąg.Następnie
Oznacza to, że konwertuje tam, gdzie może.
6
,8
Ifoobar
są ignorowane, a tylko to, co jest przed przekształca. Jeśli nic nie ma,NaN
jest zwracane.źródło
Kilka innych przykładów:
źródło