Neden parseInt (8,3) == NaN ve parseInt (16,3) == 1?


191

Okuduğum bu ama yazıldığı tam anlamadım radix argümanı ile parseInt bölüm

parseInt (_, 3) sonuç tablosu

Neden bu parseInt(8, 3)NaNve parseInt(16, 3)1?

AFAIK 8 ve 16 böylece, taban-3 sayı değildir parseInt(16, 3)dönmelidir NaNçok

ilk on baz-3 doğal sayı


4
Statik yazarak çözülen başka bir sorun (veya en azından örtük olarak tamsayı dizelere dönüştürmeme): P
Navin

4
@Navin Bunun statik ve dinamik yazmayla ilgisi yoktur (kendinizi not ettiğiniz gibi). Buradaki sorun, güçlü yazmanın aksine zayıftır.
Sven Marnach

12
Bu sorunun başlığını gördüğümde kendi kendime "muhtemelen loljavascript yüzünden" diye düşündüm. Cevapları gördüğümde içgüdümü temel olarak doğru buluyorum.
Ben Millwood

Yanıtlar:


373

Bu, insanların bildiklerinde bile her zaman yolculuk ettikleri bir şeydir. :-) Bunu aynı nedenden dolayı görüyorsunuz, parseInt("1abc")1: parseIntilk geçersiz karakterde durur ve o noktada sahip olduğu her şeyi döndürür. Ayrıştırılacak geçerli karakter yoksa, geri döner NaN.

parseInt(8, 3)" "8"baz 3'te ayrıştırma" anlamına gelir (sayıyı 8bir dizeye dönüştürdüğünü unutmayın ; teknik özellikteki ayrıntılar ). Ama baz 3'te, tek haneli sayılar sadece vardır 0, 1ve 2. "9"Sekizli ayrıştırmasını istemek gibi . Orada beri hiçbir geçerli karakterler, elinde NaN.

parseInt(16, 3)"16"3'te ayrıştırmasını istiyor. Ayrıştırılabildiğinden , ayrılıyor ve ayrıştırılamadığı için 1duruyor 6. Böylece geri döner 1.


Bu soru çok dikkat çektiğinden ve arama sonuçlarında üst sıralarda yer alabileceğinden, çeşitli ifadeleri ve uygulamaları (burada SO'nun başka bir cevabından kaldırılmış) ile dizeleri JavaScript'teki sayılara dönüştürmek için seçeneklerin bir özeti:

  • parseInt(str[, radix])- Dizenin başlangıcını olabildiğince büyük bir sayıya (tamsayı) dönüştürerek sonunda fazladan karakterleri yok sayar. Yani parseInt("10x")bir 10; xgöz ardı edilir. İsteğe bağlı bir radix (sayı tabanı) bağımsız değişkenini destekler parseInt("15", 16), 21( 15hex olarak). Herhangi bir yarıçap yoksa, dize 0x(veya 0X) ile başlamadığı sürece ondalık olduğunu varsayar ; bu durumda bunları atlar ve hex değerini alır. (Bazı tarayıcılar 0, sekizli ile başlayan dizeleri işlemek için kullanılır ; bu davranış hiçbir zaman belirtilmez ve ES5 belirtiminde özellikle izin verilmez .)NaN Ayrıştırılabilir basamak bulunamazsa döndürür .

  • parseFloat(str)- Gibi parseInt, ama kayan nokta sayıları yapar ve sadece ondalık destekler. Yine ipte ilave karakterler öylesine göz ardı edilir parseFloat("10.5x")ise 10.5( xgöz ardı edilir). Yalnızca ondalık desteklendiği parseFloat("0x15")için 0(çünkü ayrıştırma işlemi sona erer x). NaNAyrıştırılabilir rakamlar bulunmazsa döndürür .

  • Tekli +, örn. +str- (Örn. Örtük dönüşüm) Kayan nokta ve JavaScript'in standart sayı gösterimini kullanarak tüm dizeyi bir sayıya dönüştürür (sadece rakamlar ve ondalık nokta = ondalık; 0xönek = hex; 0oönek = sekizli [ES2015 +]; bazı uygulamalar bunu genişletir bir 0lidere sekizlik gibi davranmak , ancak katı modda değil). +"10x"olduğu NaN, çünkü xedilir değil görmezden geldi. +"10"olduğu 10, +"10.5"olduğu 10.5, +"0x15"olduğu 21, +"0o10"bir 8[ES2015 +]. Bir gotcha Has: +""ise 0, değil NaNTahmin edebileceğiniz gibi.

  • Number(str)- Tam olarak örtük dönüşüm gibi (örn. +Yukarıdaki tekli gibi), ancak bazı uygulamalarda daha yavaş. (Önemli olması muhtemel değil.)


8
Peki parseIntilk toStringargümandaki ilk kullanımlar ? Bu mantıklı olurdu.
evolutionxbox

16
@evolutionxbox: Evet, parseIntalgoritmanın ilk adımı : ecma-international.org/ecma-262/7.0/…
TJ Crowder

5
Sanırım ilke dönüştüğünden beri 123e-2verir ve sonra ondalık noktada durur? 11.23
ilkkachu

6
"Bu insanlar her zaman, hatta onlar hakkında bilmek bile yolculuk" -> Ben bunun bir hata olması gerektiğini düşünen tek ben miyim? Örneğin Java'da aynısını yapmak size NumberFormatExceptionher seferinde bir tane verecektir .
Wim Deblauwe

4
@SvenMarnach: Yani parçası parseInt(dizeye ilk argüman coercing) mantıklı. Amacı parseIntIs olan ayrıştırmak bir tam sayıya bir dize. Bu nedenle, dize olmayan bir şey verirseniz, dize ile temsilini başlatmak mantıklıdır. Bundan sonra ne yapar bir bütün 'nother hikaye'
TJ Crowder

54

Aynı nedenden ötürü

>> parseInt('1foobar',3)
<- 1

In doc , parseIntbir dize alır. Ve

Eğer dize bir dize değil, o zaman bir dizeye dönüştürülür

Yani 16,, 8veya '1foobar'önce dizeye dönüştürülür.

Sonra

Eğer parseIntkarşılaşmalarda belirtilen tabanda bir sayı olmayan bir karakter, onu ve tüm başarılı karakterleri yok sayar

Yani olabildiğince dönüştürür. 6, 8Ve foobargöz ardı edilir ve sadece daha önce ne dönüştürülür edilmektedir. Hiçbir şey yoksa NaNiade edilir.


0
/***** 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]

Bazı örnekler:

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 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.