Mengapa parseInt (1/0, 19) mengembalikan 18?

853

Saya memiliki masalah yang mengganggu dalam JavaScript .

> parseInt(1 / 0, 19)
> 18

Mengapa parseIntfungsinya kembali 18?

cebor
sumber
3
Menarik. Tetapi mengapa ini merupakan masalah yang mengganggu bagi Anda? Apakah Anda harus menangani Infinity dengan cara lain? Jika demikian, ifmungkin dapat membantu.
Thilo
254
Apa yang bahkan kamu lakukan yang mengharuskanmu untuk bekerja dengan nomor base-19 ATAU divisi dengan nol !?
Jack M
19
Ketika Anda bingung tentang JS, kembalilah ke kutipan ini dan ingat bahwa seluruh bahasa sialan dirancang dan diimplementasikan dalam waktu kurang dari 10 hari (menurut orang yang melakukannya).
tylerl
32
Dari FAQ: "Anda seharusnya hanya mengajukan pertanyaan praktis yang dapat dijawab berdasarkan masalah aktual yang Anda hadapi." Ini sebenarnya bukan "masalah menjengkelkan" yang sebenarnya Anda hadapi, ini adalah contoh tidak realistis yang telah beredar di internet selamanya .
Jeremy Banks
2
python melakukan hal yang sama: int ('I', 19) == 18
oberhamsi

Jawaban:

1292

Hasilnya 1/0adalah Infinity.

parseIntmemperlakukan argumen pertamanya sebagai string yang artinya pertama-tama Infinity.toString()disebut, menghasilkan string "Infinity". Jadi kerjanya sama seperti jika Anda memintanya untuk mengonversi"Infinity" dalam basis 19 ke desimal.

Berikut adalah angka dalam basis 19 bersama dengan nilai desimalnya:

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

Apa yang terjadi selanjutnya adalah parseIntmemindai input "Infinity"untuk menemukan bagian mana yang dapat diuraikan dan berhenti setelah menerima yang pertama I(karena nbukan digit yang valid pada basis 19).

Oleh karena itu berperilaku seolah-olah Anda menelepon parseInt("I", 19), yang dikonversi ke desimal 18 oleh tabel di atas.

Jon
sumber
32
@mithunsatheesh Coba parseInt('Infini',24).
Supr
112
@mithunsatheesh: Karena di base 24 njuga merupakan digit yang valid, jadi itu benar-benar berakhir parseInt("Infini", 24).
Jon
36
Mengapa seseorang ingin 'memprogram' dalam bahasa yang berperilaku seperti ini berada di luar jangkauan saya.
Frans Bouma
45
@ TransBouma: JS cantik dengan caranya sendiri. Dan sungguh, tidak ada bagian dari apa yang terjadi di sini tidak masuk akal dalam bahasa yang dinamis.
Jon
59
@ Jon: artefak ini bukan hasil dari bahasa dinamis; itu hasil dari pengetikan yang longgar. Dalam bahasa dinamis yang diketik dengan ketat, konversi implisit dari Infinity (float) ke "Infinity" (string) tidak akan terjadi, untuk mencegah kekonyolan semacam ini.
Lie Ryan
225

Berikut urutan acara:

  • 1/0 mengevaluasi ke Infinity
  • parseIntmembaca Infinitydan dengan senang hati mencatat bahwa I18 di basis 19
  • parseInt mengabaikan sisa string, karena tidak dapat dikonversi.

Perhatikan bahwa Anda akan mendapatkan hasil untuk basis apa pun >= 19, tetapi tidak untuk basis di bawahnya. Untuk basis >= 24, Anda akan mendapatkan hasil yang lebih besar, karena nmenjadi digit yang valid pada saat itu.

Craig Citro
sumber
@Thilo BTW, apa alasannya, mengapa mungkin berhenti pada 19, jika pangkalan lebih besar? Apakah Anda tahu, apa basis JS terbesar yang bisa ditafsirkannya?
Arnthor
4
@Nordvind Basis terbesar parseIntakan menerima adalah 36, karena ada 26 huruf dalam alfabet bahasa Inggris, dan konvensi adalah menggunakan digit lalu huruf sebagai himpunan digit yang valid di basis yang diberikan.
Craig Citro
4
Pada poin # 2, boleh saya sarankan berubah Infinityke "Infinity"...
CJBS
38

Untuk menambah jawaban di atas:

parseInt dimaksudkan untuk mengurai string menjadi angka (petunjuknya ada pada nama). Dalam situasi Anda, Anda tidak ingin melakukan parsing sama sekali karena 1/0 sudah menjadi angka, jadi ini adalah pilihan fungsi yang aneh. Jika Anda memiliki nomor (yang Anda lakukan) dan ingin mengubahnya menjadi basis tertentu, Anda harus menggunakan toString dengan radix sebagai gantinya.

var num = 1 / 0;
var numInBase19 = num.toString(19); // returns the string "Infinity"
kybernetikos
sumber
13

Untuk menambah jawaban di atas

parseInt(1/0,19) setara dengan parseInt("Infinity",19)

Dalam basis 19 angka 0-9dan A-I (or a-i)merupakan angka yang valid. Jadi, dari "Infinity" dibutuhkan Idari basis 19 dan dikonversi ke basis 10 yang menjadi 18 Kemudian ia mencoba untuk mengambil karakter berikutnya yaitun yang tidak ada di basis 19 sehingga membuang karakter berikutnya (sesuai perilaku javascript mengubah string ke angka )

Jadi, jika Anda menulis parseInt("Infinity",19)ATAU parseInt("I",19)ATAU parseInt("i",19)hasilnya akan sama yaitu 18.

Sekarang, jika Anda menulis parseInt("I0",19)hasilnya akan 342 seperti 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

Demikian pula, parseInt("I11",19)akan menghasilkan6518

yaitu

  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
sumber