2569 votes

Valider les nombres décimaux en JavaScript - IsNumeric()

Ce qui est le plus propre, le plus efficace de valider les nombres décimaux en JavaScript?

Les points Bonus pour:

  1. La clarté. La Solution doit être propre et simple.
  2. Croix-plate-forme.

Des cas de Test:

 01. IsNumeric('-1') => true
 02. IsNumeric('-1.5') => true
 03. IsNumeric('0') => true
 04. IsNumeric('0.42') => true
 05. IsNumeric('.42') => true
 06. IsNumeric('99,999') => *false*
 07. IsNumeric('0x89f') => *false*
 08. IsNumeric('#abcdef')=> *false*
 09. IsNumeric('1.2.3') => *false*
 10. IsNumeric('') => *false*
 11. IsNumeric('blah') => *false*

2997voto

CMS Points 315406

@Joel réponse est assez proche, mais ce sera un échec dans les cas suivants:

// Whitespace strings:
IsNumeric(' ') == true;
IsNumeric('\t\t') == true;
IsNumeric('\n\r') == true;

// Number literals:
IsNumeric(-1) == false;
IsNumeric(0) == false;
IsNumeric(1.1) == false;
IsNumeric(8e5) == false;

Il y a quelques temps, j'ai eu à mettre en œuvre un IsNumeric de la fonction, afin de vérifier si une variable contenait une valeur numérique, quel que soit son type, il pourrait être un String contenant une valeur numérique (j'ai dû tenir également compte de la notation exponentielle, etc.), un Number objet, pratiquement tout peut être passé à cette fonction, je ne pouvais pas faire tout type d'hypothèse, en prenant soin de contrainte de type (par exemple. +true == 1; mais true ne devrait pas être considérée comme "numeric").

Je pense que vaut le partage de cet ensemble de +de 30 tests unitaires faite à de nombreuses implémentations de fonction, et aussi de partager celui qui passe tous mes tests:

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

Mise à jour : Voici comment jQuery est-il maintenant (Mi-2014) :

isNumeric: function( obj ) {
    return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
}

P. S. isNaN & isFinite avoir un comportement déroutant en raison de la conversion forcée à le nombre. Dans l'ES6, Nombre.isNaN & Nombre.isFinite permettrait de résoudre ces problèmes. Gardez cela à l'esprit lors de leur utilisation.

356voto

Joel Coehoorn Points 190579

Arrrgh! N'écoutez pas l'expression régulière réponses. RegEx est dégueulasse pour cela, et je ne parle pas seulement de la performance. C'est tellement facile de faire subtil, impossible à déceler les erreurs avec votre expression régulière.

Si vous ne pouvez pas utiliser isNaN(), cela devrait fonctionner beaucoup mieux:

function IsNumeric(input)
{
    return (input - 0) == input && (''+input).replace(/^\s+|\s+$/g, "").length > 0;
}

Voici comment il fonctionne:

L' (input - 0) expression des forces de JavaScript pour faire de ce type de contrainte sur votre valeur d'entrée; il doit d'abord être interprétée comme un numéro pour l'opération de soustraction. Si la conversion d'un certain nombre d'échec, l'expression sera résultat en NaN. Cette numérique résultat est ensuite comparé à la valeur d'origine que vous avez passé en. Depuis le côté gauche est désormais numérique, type de contrainte est de nouveau utilisé. Maintenant que les contributions des deux parties a été contrainte de même type à partir de la même valeur d'origine, on pourrait penser qu'elle devrait toujours être le même (toujours vrai). Cependant, il y a une règle spéciale qui, dit - NaN n'est jamais égal à NaN, et donc une valeur qui ne peut pas être converti en nombre (et uniquement des valeurs qui ne peuvent être converties en nombres) résultat sera faux.

La vérification de la longueur est pour un cas particulier impliquant des chaînes vides. Notez également qu'il tombe sur votre 0x89f test, mais c'est parce que dans de nombreux environnements, c'est un bon moyen de définir un nombre littéral. Si vous voulez attraper que le scénario vous pouvez ajouter un contrôle supplémentaire. Encore mieux, si c'est votre raison pour ne pas utiliser isNaN() alors juste envelopper de votre propre fonction autour de isNaN() qui peut aussi faire la vérification supplémentaire.

En résumé, si vous voulez savoir si une valeur peut être convertie en nombre, en fait on essaie de le convertir en nombre.


Je suis retourné et a fait quelques recherches pour pourquoi un blanc de la chaîne n'a pas eu les résultats attendus, et je pense que je comprends maintenant: une chaîne vide est contrainte d' 0 plutôt que d' NaN. Découper la chaîne avant de la longueur de la vérification de gérer ce cas. Notez que j'ai opté pour une regex à base de garniture plutôt que de la .fonction trim() afin de soutenir IE8 (et oui, je suis conscient de l'ironie dans le démarrage de ma réponse par dissing les regex et puis, à l'aide de l'un dans le code, même si de façon limitée seulement). À propos de cette période de l'année prochaine lors de la Windows XP n'est plus supporté, je vais revenir et de le mettre à jour pour utiliser le .fonction trim () (et la suppression de ces deux phrases... si je me souviens).

Exécute les tests unitaires contre le nouveau code, et il échoue uniquement sur l'infini et littéraux booléens, et la seule fois que doit être un problème si vous êtes de la génération de code (vraiment, qui serait de type dans un sens littéral et vérifier si elle est numérique? Vous devriez le savoir), et qui serait une étrange code à générer.

Mais, encore une fois, la seule raison de l'utilisation de ce est si pour une raison quelconque, vous devez éviter les isNaN().

85voto

Michael Haren Points 42641

De cette façon, semble bien fonctionner:

function IsNumeric(input){
    var RE = /^-{0,1}\d*\.{0,1}\d+$/;
    return (RE.test(input));
}

Et pour le tester:

// alert(TestIsNumeric());

function TestIsNumeric(){
    var results = ''
    results += (IsNumeric('-1')?"Pass":"Fail") + ": IsNumeric('-1') => true\n";
    results += (IsNumeric('-1.5')?"Pass":"Fail") + ": IsNumeric('-1.5') => true\n";
    results += (IsNumeric('0')?"Pass":"Fail") + ": IsNumeric('0') => true\n";
    results += (IsNumeric('0.42')?"Pass":"Fail") + ": IsNumeric('0.42') => true\n";
    results += (IsNumeric('.42')?"Pass":"Fail") + ": IsNumeric('.42') => true\n";
    results += (!IsNumeric('99,999')?"Pass":"Fail") + ": IsNumeric('99,999') => false\n";
    results += (!IsNumeric('0x89f')?"Pass":"Fail") + ": IsNumeric('0x89f') => false\n";
    results += (!IsNumeric('#abcdef')?"Pass":"Fail") + ": IsNumeric('#abcdef') => false\n";
    results += (!IsNumeric('1.2.3')?"Pass":"Fail") + ": IsNumeric('1.2.3') => false\n";
    results += (!IsNumeric('')?"Pass":"Fail") + ": IsNumeric('') => false\n";
    results += (!IsNumeric('blah')?"Pass":"Fail") + ": IsNumeric('blah') => false\n";

    return results;
}

J'ai emprunté cette expression rationnelle de http://www.codetoad.com/javascript/isnumeric.asp. Explication:

/^ match beginning of string
-{0,1} optional negative sign
\d* optional digits
\.{0,1} optional decimal point
\d+ at least one digit
$/ match end of string

58voto

camomileCase Points 884

Yahoo! L'INTERFACE utilisateur utilise ceci:

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X