Pourquoi parseInt (1/0, 19) renvoie 18?

853

J'ai un problème gênant en JavaScript .

> parseInt(1 / 0, 19)
> 18

Pourquoi la parseIntfonction revient-elle 18?

cebor
la source
3
Intéressant. Mais pourquoi est-ce un problème gênant pour vous? Devez-vous gérer Infinity autrement? Si c'est le cas, un ifpourrait aider.
Thilo
254
Que diable faisiez-vous même qui vous obligeait à travailler avec les numéros de base 19 OU la division par zéro!?
Jack M
19
Lorsque vous vous trompez au sujet de JS, revenez simplement à cette citation et rappelez-vous que le fichu langage a été conçu et mis en œuvre en moins de 10 jours (selon la personne qui l'a fait).
tylerl
32
De la FAQ: "Vous ne devriez poser que des questions pratiques et fiables basées sur les problèmes réels que vous rencontrez." Ce n'est pas réellement un "problème ennuyeux" auquel vous êtes réellement confronté, c'est un exemple irréaliste qui flotte depuis toujours sur Internet .
Jeremy Banks
2
python fait la même chose: int ('I', 19) == 18
oberhamsi

Réponses:

1292

Le résultat de 1/0est Infinity.

parseInttraite son premier argument comme une chaîne, ce qui signifie que tout d'abord Infinity.toString()est appelé, produisant la chaîne "Infinity". Il fonctionne donc de la même manière que si vous lui aviez demandé de convertir "Infinity"en base 19 en décimal.

Voici les chiffres de la base 19 avec leurs valeurs décimales:

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

Ce qui se passe ensuite est que parseIntbalaye l'entrée "Infinity"pour trouver quelle partie de celle-ci peut être analysée et s'arrête après avoir accepté le premier I(car ce nn'est pas un chiffre valide dans la base 19).

Par conséquent, il se comporte comme si vous appeliez parseInt("I", 19), ce qui se transforme en décimal 18 par le tableau ci-dessus.

Jon
la source
32
@mithunsatheesh Essayez parseInt('Infini',24).
2012
112
@mithunsatheesh: Parce que dans la base 24 nest également un chiffre valide, il finit par le faire parseInt("Infini", 24).
Jon
36
Pourquoi quelqu'un veut «programmer» dans une langue qui se comporte comme ça me dépasse.
Frans Bouma
45
@FransBouma: JS est beau à sa manière. Et vraiment, aucune partie de ce qui se passe ici n'est déraisonnable dans un langage dynamique.
Jon
59
@Jon: cet artefact n'est pas le résultat d'un langage dynamique; c'est le résultat d'une frappe lâche. Dans un langage dynamique strictement typé, la conversion implicite d'Infinity (float) en "Infinity" (chaîne) ne se produirait pas, pour éviter ce genre de bêtise.
Lie Ryan
225

Voici la séquence des événements:

  • 1/0 évalue à Infinity
  • parseIntlit Infinityet note avec bonheur qui Iest de 18 en base 19
  • parseInt ignore le reste de la chaîne, car elle ne peut pas être convertie.

Notez que vous obtiendrez un résultat pour n'importe quelle base >= 19, mais pas pour les bases en dessous. Pour les bases >= 24, vous obtiendrez un résultat plus grand, car il ndevient un chiffre valide à ce stade.

Craig Citro
la source
@Thilo BTW, quelle serait la raison, pourquoi il pourrait s'arrêter à 19, si la base est supérieure? Savez-vous, quelle est la meilleure base que JS puisse interpréter?
Arnthor
4
@Nordvind La plus grande base parseIntacceptera est 36, car il y a 26 lettres dans l'alphabet anglais, et la convention est d'utiliser des chiffres puis des lettres comme ensemble de chiffres valides dans la base donnée.
Craig Citro
4
Au point n ° 2, puis-je suggérer de passer Infinityà "Infinity"...
CJBS
38

Pour ajouter aux réponses ci-dessus:

parseInt est destiné à analyser les chaînes en nombres (l'indice est dans le nom). Dans votre situation, vous ne voulez pas du tout analyser car 1/0 est déjà un nombre, c'est donc un choix de fonction étrange. Si vous avez un nombre (ce que vous faites) et que vous souhaitez le convertir en une base particulière, vous devez plutôt utiliser toString avec un radix .

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

Pour ajouter aux réponses ci-dessus

parseInt(1/0,19) est équivalent à parseInt("Infinity",19)

Dans la base 19 numéros 0-9et A-I (or a-i)sont des numéros valides. Donc, à partir de "l'infini", il prend Ide la base 19 et se convertit en base 10 qui devient 18 Ensuite, il essaie de prendre le caractère suivant, c'est-à-dire nqui n'est pas présent en base 19, donc il rejette les caractères suivants (selon le comportement de javascript de la conversion de la chaîne en nombre )

Donc, si vous écrivez parseInt("Infinity",19)OU parseInt("I",19)OU parseInt("i",19)le résultat sera le même, c'est-à-dire 18.

Maintenant, si vous écrivez, parseInt("I0",19)le résultat sera 342 comme 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

De même, parseInt("I11",19)entraînera6518

c'est à dire

  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
la source