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

2377

Quel est le moyen le plus propre et le plus efficace de valider des nombres décimaux en JavaScript?

Points bonus pour:

  1. Clarté. La solution doit être propre et simple.
  2. Multiplateforme.

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
Michael Haren
la source
256
Juste une note 99,999 est un nombre valide en France, c'est le même que 99,999 au format uk / us, donc si vous lisez dans une chaîne de disons un formulaire d'entrée, alors 99,999 peut être vrai.
Re0sless
5
Consultez également cet article et les excellents commentaires .
powtac
79
La virgule décimale est la norme dans toute l'Europe et la Russie (sauf au Royaume-Uni)
Calmarius
90
jQuery 1.7 a introduit la jQuery.isNumericfonction utilitaire: api.jquery.com/jQuery.isNumeric
Ates Goral
24
jQuery.isNumericéchouera au septième cas de test de l'OP ( IsNumeric('0x89f') => *false*). Je ne sais pas si je suis d'accord avec ce cas de test, cependant.
Tim Lehner

Réponses:

2898

@ La réponse de Joel est assez proche, mais elle échouera 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 quelque temps, j'ai dû implémenter une IsNumericfonction, pour savoir si une variable contenait une valeur numérique, quel que soit son type , elle pouvait être une Stringcontenant une valeur numérique (je devais considérer aussi la notation exponentielle, etc.), un Numberobjet, pratiquement tout pouvait être transmis à cette fonction, je ne pouvais pas faire d'hypothèses de type, en prenant soin de la contrainte de type (par exemple, +true == 1;mais truene devrait pas être considéré comme "numeric").

Je pense qu'il vaut la peine de partager cet ensemble de tests unitaires +30 effectués sur de nombreuses implémentations de fonctions, et de partager celui qui réussit tous mes tests:

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

PS isNaN & isFinite ont un comportement déroutant en raison de la conversion forcée en nombre. Dans ES6, Number.isNaN & Number.isFinite résoudrait ces problèmes. Gardez cela à l'esprit lorsque vous les utilisez.


Mise à jour : voici comment jQuery le fait maintenant (2.2-stable) :

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

Mise à jour : Angular 4.3 :

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}
CMS
la source
26
cela échoue avec d'autres paramètres régionaux où nous utilisons des virgules décimales, mais ajoutez `n = n.replace (/, /,". "); ' avant le retour pour le réparer.
Zoltan Lengyel
5
@RobG, ce comportement est intentionnel 2e308 > Number.MAX_VALUEdepuis 2e308 == Infinity. Si vous voulez une fonction qui renvoie trueégalement des valeurs d'infini positives et négatives, vérifiez la fonction n ° 2 dans la suite de tests . À votre santé.
CMS
39
Soit dit en passant, les tests unitaires sont maintenant utilisés par le projet jQuery
CMS
7
jQuery utilise désormais également cette implémentation.
RichardTowers
4
La solution ici est d'utiliser simplement JQuery. Ils ont maintenant une meilleure implémentation de ceci: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli
337

Arrrgh! N'écoutez pas les réponses d'expression régulière. RegEx est exagéré pour cela, et je ne parle pas seulement de performances. Il est si facile de faire des erreurs subtiles, impossibles à repérer avec votre expression régulière.

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

function IsNumeric(input)
{
    return (input - 0) == input && (''+input).trim().length > 0;
}

Voici comment ça fonctionne:

L' (input - 0)expression force JavaScript à effectuer une coercition de type sur votre valeur d'entrée; il doit d'abord être interprété comme un nombre pour l'opération de soustraction. Si cette conversion en un nombre échoue, l'expression se traduira par NaN. Ce résultat numérique est ensuite comparé à la valeur d'origine que vous avez transmise. Comme le côté gauche est désormais numérique, le type coercition est à nouveau utilisé. Maintenant que l'entrée des deux côtés a été contrainte au même type à partir de la même valeur d'origine, vous penseriez qu'ils devraient toujours être les mêmes (toujours vrai). Cependant, il existe une règle spéciale qui dit NaNn'est jamais égal à NaN, et donc une valeur qui ne peut pas être convertie en nombre (et seules les valeurs qui ne peuvent pas être converties en nombres) se traduira par false.

Le contrôle de la longueur concerne un cas particulier impliquant des chaînes vides. Notez également qu'il tombe sur votre test 0x89f, mais c'est parce que dans de nombreux environnements, c'est une bonne façon de définir un nombre littéral. Si vous souhaitez intercepter ce scénario spécifique, vous pouvez ajouter une vérification supplémentaire. Encore mieux, si c'est votre raison de ne pas l'utiliser, isNaN()enveloppez simplement votre propre fonction isNaN()qui peut également faire la vérification supplémentaire.

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


Je suis retourné et j'ai fait des recherches pour savoir pourquoi une chaîne d'espaces blancs n'avait pas la sortie attendue, et je pense que je l'obtiens maintenant: une chaîne vide est contrainte à 0plutôt que NaN. Il suffit de couper la chaîne avant la vérification de la longueur pour gérer ce cas.

Exécuter les tests unitaires contre le nouveau code et il échoue uniquement sur les littéraux infini et booléen, et le seul moment qui devrait être un problème est si vous générez du code (vraiment, qui taperait un littéral et vérifierait s'il est numérique? Vous devez savoir ), et ce serait un code étrange à générer.

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

Joel Coehoorn
la source
28
Cela échoue sur les chaînes d'espaces blancs, par exemple IsNumeric(' '), IsNumeric('\n\t')etc. tous les retourstrue
Crescent Fresh
29
Il échouera également lors de la vérification Numberlittérale de IsNumeric(5) == false;l'ensemble des tests unitaires que j'ai publiés, cette fonction est le numéro 16de la suite de tests. stackoverflow.com/questions/18082/…
CMS
20
Je ne peux pas croire que personne n'ait signalé l'utilisation d'une expression régulière (remplacer) après avoir averti de ne pas utiliser d'expressions régulières ... Certes, le remplacement d'un espace est plus simple qu'une analyse de nombre, mais c'est toujours "icky".
Patrick M
1
@Oriol C'est un gros problème ... sans correctif de sécurité publié après cette date, s'éloigner de XP devrait être une priorité.
Joel Coehoorn
1
@Oriol XP ou non, si vous utilisez IE8 ou une version antérieure, vous utilisez un logiciel horriblement obsolète. Accordé XP ne peut pas exécuter IE9 +, utilisez donc Chrome ou FF. Les personnes vivant dans le passé utilisant IE8 sont le fléau de l'existence de nombreux développeurs Web. Si je pouvais revenir sur le temps que j'ai passé à m'assurer que du bon code fonctionne également dans IE8 ... en s'assurant qu'il fonctionne de la même manière dans Windows 3.1.
chiliNUT
70

Cette façon semble bien fonctionner:

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

En une seule ligne:

const IsNumeric = (num) => /^-{0,1}\d*\.{0,1}\d+$/.test(num);

Et pour le tester:

const IsNumeric = (num) => /^-{0,1}\d*\.{0,1}\d+$/.test(num);
    
    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;
    }

console.log(TestIsNumeric());
.as-console-wrapper { max-height: 100% !important; top: 0; }

J'ai emprunté cette expression régulière à 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
Michael Haren
la source
1
// DEVRAIT ÉGALEMENT ÊTRE AJOUTÉ À VOTRE TEST résultats + = (! IsNumeric ('-')? "Pass": "Fail") + ": IsNumeric ('-') => false \ n"; results + = (! IsNumeric ('01 ')? "Pass": "Fail") + ": IsNumeric ('01') => false \ n"; results + = (! IsNumeric ('- 01')? "Pass": "Fail") + ": IsNumeric ('- 01') => false \ n"; results + = (! IsNumeric ('000')? "Pass": "Fail") + ": IsNumeric ('000') => false \ n";
Dan
qu'est-ce que cela fait? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
appelez-moi le
"{0,1}" peut-il être remplacé par "?", donc votre expression rationnelle ressemblera à ceci: /^-?\d*\.?\d+$/?
Cloud
agréable et simple.
le briseur
53

Yahoo! L'interface utilisateur utilise ceci:

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}
camomileCase
la source
25
C'est plus vérifier le type de variable que le contenu du nombre. Il échouera également sur les numéros créés avec new Number(1).
alex
4
Comme le dit alex, cela ne répond pas réellement à la question posée car cela échouera si o = "1001".
Cas le
50
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

Cela fonctionne également pour les numéros de type 0x23.

user189277
la source
29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Retour au truelieu de false.
Oriol
49

La réponse acceptée a échoué à votre test n ° 7 et je suppose que c'est parce que vous avez changé d'avis. C'est donc une réponse à la réponse acceptée, avec laquelle j'ai eu des problèmes.

Au cours de certains projets, j'ai dû valider certaines données et être aussi certain que possible qu'il s'agit d'une valeur numérique javascript qui peut être utilisée dans des opérations mathématiques.

jQuery et certaines autres bibliothèques javascript incluent déjà une telle fonction, généralement appelée isNumeric. Il existe également un article sur stackoverflow qui a été largement accepté comme réponse, la même routine générale que les bibliothèques susmentionnées utilisent.

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

Tout d'abord, le code ci-dessus retournerait vrai si l'argument était un tableau de longueur 1 et que cet élément unique était d'un type considéré comme numérique par la logique ci-dessus. À mon avis, si c'est un tableau, ce n'est pas numérique.

Pour atténuer ce problème, j'ai ajouté une vérification pour actualiser les tableaux de la logique

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n);
}

Bien sûr, vous pouvez également utiliser Array.isArray, jquery $.isArrayou prototype Object.isArrayau lieu deObject.prototype.toString.call(n) !== '[object Array]'

Mon deuxième problème était que les chaînes littérales entières hexadécimales négatives ("-0xA" -> -10) n'étaient pas comptées comme numériques. Cependant, les chaînes littérales entières hexadécimales positives ("0xA" -> 10) ont été traitées comme des valeurs numériques. J'avais besoin des deux pour être numérique valide.

J'ai ensuite modifié la logique pour en tenir compte.

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

Si vous êtes inquiet à propos de la création de l'expression régulière à chaque appel de la fonction, vous pouvez la réécrire dans une fermeture, quelque chose comme ceci

var isNumber = (function () {
  var rx = /^-/;

  return function (n) {
      return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(rx, ''));
  };
}());

J'ai ensuite pris des cas de test CMS +30 et cloné les tests sur jsfiddle ajouté mes cas de test supplémentaires et ma solution décrite ci-dessus.

Cela ne remplacera peut-être pas la réponse largement acceptée / utilisée, mais si c'est plus ce à quoi vous vous attendez en tant que résultats de votre fonction isNumeric, nous espérons que cela vous sera utile.

EDIT: Comme l'a souligné Bergi , il existe d'autres objets possibles qui pourraient être considérés comme numériques et il serait préférable de mettre sur liste blanche que sur liste noire. Dans cet esprit, j'ajouterais aux critères.

Je souhaite que ma fonction isNumeric prenne en compte uniquement les nombres ou les chaînes

Dans cette optique, il serait préférable d'utiliser

function isNumber(n) {
  return (Object.prototype.toString.call(n) === '[object Number]' || Object.prototype.toString.call(n) === '[object String]') &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

Testez les solutions

var testHelper = function() {

  var testSuite = function() {
    test("Integer Literals", function() {
      ok(isNumber("-10"), "Negative integer string");
      ok(isNumber("0"), "Zero string");
      ok(isNumber("5"), "Positive integer string");
      ok(isNumber(-16), "Negative integer number");
      ok(isNumber(0), "Zero integer number");
      ok(isNumber(32), "Positive integer number");
      ok(isNumber("040"), "Octal integer literal string");
      ok(isNumber(0144), "Octal integer literal");
      ok(isNumber("-040"), "Negative Octal integer literal string");
      ok(isNumber(-0144), "Negative Octal integer literal");
      ok(isNumber("0xFF"), "Hexadecimal integer literal string");
      ok(isNumber(0xFFF), "Hexadecimal integer literal");
      ok(isNumber("-0xFF"), "Negative Hexadecimal integer literal string");
      ok(isNumber(-0xFFF), "Negative Hexadecimal integer literal");
    });

    test("Foating-Point Literals", function() {
      ok(isNumber("-1.6"), "Negative floating point string");
      ok(isNumber("4.536"), "Positive floating point string");
      ok(isNumber(-2.6), "Negative floating point number");
      ok(isNumber(3.1415), "Positive floating point number");
      ok(isNumber(8e5), "Exponential notation");
      ok(isNumber("123e-2"), "Exponential notation string");
    });

    test("Non-Numeric values", function() {
      equals(isNumber(""), false, "Empty string");
      equals(isNumber("        "), false, "Whitespace characters string");
      equals(isNumber("\t\t"), false, "Tab characters string");
      equals(isNumber("abcdefghijklm1234567890"), false, "Alphanumeric character string");
      equals(isNumber("xabcdefx"), false, "Non-numeric character string");
      equals(isNumber(true), false, "Boolean true literal");
      equals(isNumber(false), false, "Boolean false literal");
      equals(isNumber("bcfed5.2"), false, "Number with preceding non-numeric characters");
      equals(isNumber("7.2acdgs"), false, "Number with trailling non-numeric characters");
      equals(isNumber(undefined), false, "Undefined value");
      equals(isNumber(null), false, "Null value");
      equals(isNumber(NaN), false, "NaN value");
      equals(isNumber(Infinity), false, "Infinity primitive");
      equals(isNumber(Number.POSITIVE_INFINITY), false, "Positive Infinity");
      equals(isNumber(Number.NEGATIVE_INFINITY), false, "Negative Infinity");
      equals(isNumber(new Date(2009, 1, 1)), false, "Date object");
      equals(isNumber(new Object()), false, "Empty object");
      equals(isNumber(function() {}), false, "Instance of a function");
      equals(isNumber([]), false, "Empty Array");
      equals(isNumber(["-10"]), false, "Array Negative integer string");
      equals(isNumber(["0"]), false, "Array Zero string");
      equals(isNumber(["5"]), false, "Array Positive integer string");
      equals(isNumber([-16]), false, "Array Negative integer number");
      equals(isNumber([0]), false, "Array Zero integer number");
      equals(isNumber([32]), false, "Array Positive integer number");
      equals(isNumber(["040"]), false, "Array Octal integer literal string");
      equals(isNumber([0144]), false, "Array Octal integer literal");
      equals(isNumber(["-040"]), false, "Array Negative Octal integer literal string");
      equals(isNumber([-0144]), false, "Array Negative Octal integer literal");
      equals(isNumber(["0xFF"]), false, "Array Hexadecimal integer literal string");
      equals(isNumber([0xFFF]), false, "Array Hexadecimal integer literal");
      equals(isNumber(["-0xFF"]), false, "Array Negative Hexadecimal integer literal string");
      equals(isNumber([-0xFFF]), false, "Array Negative Hexadecimal integer literal");
      equals(isNumber([1, 2]), false, "Array with more than 1 Positive interger number");
      equals(isNumber([-1, -2]), false, "Array with more than 1 Negative interger number");
    });
  }

  var functionsToTest = [

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

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

    function(n) {
      return !isNaN((n));
    },

    function(n) {
      return !isNaN(parseFloat(n));
    },

    function(n) {
      return typeof(n) != "boolean" && !isNaN(n);
    },

    function(n) {
      return parseFloat(n) === Number(n);
    },

    function(n) {
      return parseInt(n) === Number(n);
    },

    function(n) {
      return !isNaN(Number(String(n)));
    },

    function(n) {
      return !isNaN(+('' + n));
    },

    function(n) {
      return (+n) == n;
    },

    function(n) {
      return n && /^-?\d+(\.\d+)?$/.test(n + '');
    },

    function(n) {
      return isFinite(Number(String(n)));
    },

    function(n) {
      return isFinite(String(n));
    },

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

    function(n) {
      return parseFloat(n) == n;
    },

    function(n) {
      return (n - 0) == n && n.length > 0;
    },

    function(n) {
      return typeof n === 'number' && isFinite(n);
    },

    function(n) {
      return !Array.isArray(n) && !isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
    }

  ];


  // Examines the functionsToTest array, extracts the return statement of each function
  // and fills the toTest select element.
  var fillToTestSelect = function() {
    for (var i = 0; i < functionsToTest.length; i++) {
      var f = functionsToTest[i].toString();
      var option = /[\s\S]*return ([\s\S]*);/.exec(f)[1];
      $("#toTest").append('<option value="' + i + '">' + (i + 1) + '. ' + option + '</option>');
    }
  }

  var performTest = function(functionNumber) {
    reset(); // Reset previous test
    $("#tests").html(""); //Clean test results
    isNumber = functionsToTest[functionNumber]; // Override the isNumber global function with the one to test
    testSuite(); // Run the test

    // Get test results
    var totalFail = 0;
    var totalPass = 0;
    $("b.fail").each(function() {
      totalFail += Number($(this).html());
    });
    $("b.pass").each(function() {
      totalPass += Number($(this).html());
    });
    $("#testresult").html(totalFail + " of " + (totalFail + totalPass) + " test failed.");

    $("#banner").attr("class", "").addClass(totalFail > 0 ? "fail" : "pass");
  }

  return {
    performTest: performTest,
    fillToTestSelect: fillToTestSelect,
    testSuite: testSuite
  };
}();


$(document).ready(function() {
  testHelper.fillToTestSelect();
  testHelper.performTest(0);

  $("#toTest").change(function() {
    testHelper.performTest($(this).children(":selected").val());
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="https://rawgit.com/Xotic750/testrunner-old/master/testrunner.js" type="text/javascript"></script>
<link href="https://rawgit.com/Xotic750/testrunner-old/master/testrunner.css" rel="stylesheet" type="text/css">
<h1>isNumber Test Cases</h1>

<h2 id="banner" class="pass"></h2>

<h2 id="userAgent">Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11</h2>

<div id="currentFunction"></div>

<div id="selectFunction">
  <label for="toTest" style="font-weight:bold; font-size:Large;">Select function to test:</label>
  <select id="toTest" name="toTest">
  </select>
</div>

<div id="testCode"></div>

<ol id="tests">
  <li class="pass">
    <strong>Integer Literals <b style="color:black;">(0, 10, 10)</b></strong>

    <ol style="display: none;">
      <li class="pass">Negative integer string</li>

      <li class="pass">Zero string</li>

      <li class="pass">Positive integer string</li>

      <li class="pass">Negative integer number</li>

      <li class="pass">Zero integer number</li>

      <li class="pass">Positive integer number</li>

      <li class="pass">Octal integer literal string</li>

      <li class="pass">Octal integer literal</li>

      <li class="pass">Hexadecimal integer literal string</li>

      <li class="pass">Hexadecimal integer literal</li>
    </ol>
  </li>

  <li class="pass">
    <strong>Foating-Point Literals <b style="color:black;">(0, 6, 6)</b></strong>

    <ol style="display: none;">
      <li class="pass">Negative floating point string</li>

      <li class="pass">Positive floating point string</li>

      <li class="pass">Negative floating point number</li>

      <li class="pass">Positive floating point number</li>

      <li class="pass">Exponential notation</li>

      <li class="pass">Exponential notation string</li>
    </ol>
  </li>

  <li class="pass">
    <strong>Non-Numeric values <b style="color:black;">(0, 18, 18)</b></strong>

    <ol style="display: none;">
      <li class="pass">Empty string: false</li>

      <li class="pass">Whitespace characters string: false</li>

      <li class="pass">Tab characters string: false</li>

      <li class="pass">Alphanumeric character string: false</li>

      <li class="pass">Non-numeric character string: false</li>

      <li class="pass">Boolean true literal: false</li>

      <li class="pass">Boolean false literal: false</li>

      <li class="pass">Number with preceding non-numeric characters: false</li>

      <li class="pass">Number with trailling non-numeric characters: false</li>

      <li class="pass">Undefined value: false</li>

      <li class="pass">Null value: false</li>

      <li class="pass">NaN value: false</li>

      <li class="pass">Infinity primitive: false</li>

      <li class="pass">Positive Infinity: false</li>

      <li class="pass">Negative Infinity: false</li>

      <li class="pass">Date object: false</li>

      <li class="pass">Empty object: false</li>

      <li class="pass">Instance of a function: false</li>
    </ol>
  </li>
</ol>

<div id="main">
  This page contains tests for a set of isNumber functions. To see them, take a look at the source.
</div>

<div>
  <p class="result">Tests completed in 0 milliseconds.
    <br>0 tests of 0 failed.</p>
</div>

Xotic750
la source
2
C'est à mon avis la fonction la plus protégée; le dernier. La réponse acceptée couvre probablement 99,99% de tous les cas, mais celui-ci contient probablement 100% a) des cas avec un petit surcoût.
Samuel
Vous avez oublié le littéral "99,999" Foating-Point. C'est un numéro valide dans toute l'Europe sauf au Royaume
Andrii Horda
Ce n'était pas oublié, ce n'était pas quelque chose que je considérais comme un numérique dans le sens des nombres Javascript, a également déclaré l'OPIsNumeric('99,999') => false
Xotic750
34

Ouais, le intégré isNaN(object)sera beaucoup plus rapide que toute analyse syntaxique de regex, car il est intégré et compilé, au lieu d'être interprété à la volée.

Bien que les résultats soient quelque peu différents de ce que vous recherchez ( essayez-le ):

                                              // IS NUMERIC
document.write(!isNaN('-1') + "<br />");      // true
document.write(!isNaN('-1.5') + "<br />");    // true
document.write(!isNaN('0') + "<br />");       // true
document.write(!isNaN('0.42') + "<br />");    // true
document.write(!isNaN('.42') + "<br />");     // true
document.write(!isNaN('99,999') + "<br />");  // false
document.write(!isNaN('0x89f') + "<br />");   // true
document.write(!isNaN('#abcdef') + "<br />"); // false
document.write(!isNaN('1.2.3') + "<br />");   // false
document.write(!isNaN('') + "<br />");        // true
document.write(!isNaN('blah') + "<br />");    // false
travis
la source
18

Utilisez la fonction isNaN. Je crois que si vous testez, !isNaN(yourstringhere)cela fonctionne bien pour l'une de ces situations.

bubbassauro
la source
Remarque:! IsNaN (null) == true puisque Number (null) == 0
Jonathan Lonowski
if (! (x == null || isNaN (x))) alert ("isNumeric"); // Mais cette solution accepte 0x40 donc ce n'est toujours pas ce que l'op voulait.
certains
Notez que isNaN ("Infinity") === false, ce qui n'est probablement pas non plus ce que vous voulez (mais cela ne se produira pas dans la vraie vie).
Erik Hesselink
16

Depuis jQuery 1.7, vous pouvez utiliser jQuery.isNumeric():

$.isNumeric('-1');      // true
$.isNumeric('-1.5');    // true
$.isNumeric('0');       // true
$.isNumeric('0.42');    // true
$.isNumeric('.42');     // true
$.isNumeric('0x89f');   // true (valid hexa number)
$.isNumeric('99,999');  // false
$.isNumeric('#abcdef'); // false
$.isNumeric('1.2.3');   // false
$.isNumeric('');        // false
$.isNumeric('blah');    // false

Notez simplement que contrairement à ce que vous avez dit, 0x89fest un nombre valide (hexa)

Kuf
la source
L'OP veut un nombre décimal valide , donc jQuery isNumeric ne convient pas. Il échoue également pour de très grands nombres.
RobG
13

Cela peut être fait sans RegExp comme

function IsNumeric(data){
    return parseFloat(data)==data;
}
Aquatique
la source
5
Si nous utilisons ==, cela retournera vrai même pour les nombres présentés sous forme de chaînes. Ainsi, le "42" sera compté comme un numéro valide en cas de "==" et sera considéré comme invalide en cas de ===
Aquatic
cela renvoie vrai sur "-0.", "-.0", ".0" et "0".
Janus Troelsen
8
return (input - 0) == input && input.length > 0;

n'a pas fonctionné pour moi. Quand j'ai mis une alerte et testé, input.lengthc'était undefined. Je pense qu'il n'y a aucune propriété pour vérifier la longueur entière. Donc ce que j'ai fait

var temp = '' + input;
return (input - 0) == input && temp.length > 0;

Cela a bien fonctionné.

jayakumar
la source
7

Si je ne me trompe pas, cela devrait correspondre à toute valeur de numéro JavaScript valide, à l'exclusion des constantes ( Infinity, NaN) et des opérateurs de signe +/ -(car ils ne font pas réellement partie du nombre en ce qui me concerne, ce sont des opérateurs distincts):

J'en avais besoin pour un tokenizer, où l'envoi du numéro à JavaScript pour évaluation n'était pas une option ... Ce n'est certainement pas l'expression régulière la plus courte possible, mais je pense qu'il capture toutes les subtilités les plus fines de la syntaxe numérique de JavaScript.

/^(?:(?:(?:[1-9]\d*|\d)\.\d*|(?:[1-9]\d*|\d)?\.\d+|(?:[1-9]\d*|\d)) 
(?:[e]\d+)?|0[0-7]+|0x[0-9a-f]+)$/i

Les nombres valides comprennent:

 - 0
 - 00
 - 01
 - 10
 - 0e1
 - 0e01
 - .0
 - 0.
 - .0e1
 - 0.e1
 - 0.e00
 - 0xf
 - 0Xf

Des nombres invalides seraient

 - 00e1
 - 01e1
 - 00.0
 - 00x0
 - .
 - .e0
Jonathan Spooner
la source
7

Le seul problème que j'ai eu avec la réponse de @ CMS est l'exclusion de NaNet Infinity, qui sont des numéros utiles dans de nombreuses situations. Une façon de vérifier NaNl » est de vérifier les valeurs numériques qui ne sont pas eux - mêmes égaux, NaN != NaN! Il y a donc vraiment 3 tests que vous aimeriez traiter ...

function isNumber(n) {
  n = parseFloat(n);
  return !isNaN(n) || n != n;
}
function isFiniteNumber(n) {
  n = parseFloat(n);
  return !isNaN(n) && isFinite(n);
}    
function isComparableNumber(n) {
  n = parseFloat(n);
  return (n >=0 || n < 0);
}

isFiniteNumber('NaN')
false
isFiniteNumber('OxFF')
true
isNumber('NaN')
true
isNumber(1/0-1/0)
true
isComparableNumber('NaN')
false
isComparableNumber('Infinity')
true

My isComparableNumber est assez proche d'une autre réponse élégante , mais gère les représentations hexadécimales et autres chaînes de nombres.

95%
la source
6

Pour moi, c'est la meilleure façon:

isNumber : function(v){
   return typeof v === 'number' && isFinite(v);
}
InsertNameHere
la source
Malheureusement, c'est un vérificateur numérique STRICT qui échouera pour toute chaîne contenant uniquement des lettres numériques, comme "0" etc ...
Arman McHitarian
6

Je voudrais ajouter ce qui suit:

1. IsNumeric('0x89f') => true
2. IsNumeric('075') => true

Les nombres hexadécimaux positifs commencent par 0xet les nombres hexadécimaux négatifs commencent par -0x. Les nombres d'octets positifs commencent par 0et les nombres d'octets négatifs commencent par -0. Celui-ci prend en compte la plupart de ce qui a déjà été mentionné, mais comprend les nombres hexadécimaux et octaux, scientifique négatif, Infinity et a supprimé scientifique décimal ( 4e3.2n'est pas valide).

function IsNumeric(input){
  var RE = /^-?(0|INF|(0[1-7][0-7]*)|(0x[0-9a-fA-F]+)|((0|[1-9][0-9]*|(?=[\.,]))([\.,][0-9]+)?([eE]-?\d+)?))$/;
  return (RE.test(input));
}
Marius
la source
6

Je pense que la fonction parseFloat peut faire tout le travail ici. La fonction ci-dessous passe tous les tests de cette page, notamment isNumeric(Infinity) == true:

function isNumeric(n) {

    return parseFloat(n) == n;
}
John Mikic
la source
Oui, je suis également arrivé à cette conclusion. J'aime aussi beaucoup la façon dont les tableaux sont traités en utilisant cette méthode; un tableau avec une seule valeur compte comme cette valeur, mais tout le reste échoue: IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; mais j'imagine que c'est une question de goût!
Mark Birbeck
4

Quelques tests à ajouter:

IsNumeric('01.05') => false
IsNumeric('1.') => false
IsNumeric('.') => false

Je suis venu avec ceci:

function IsNumeric(input) {
    return /^-?(0|[1-9]\d*|(?=\.))(\.\d+)?$/.test(input);
}

La solution couvre:

  • Un signe négatif facultatif au début
  • Un seul zéro, ou un ou plusieurs chiffres ne commençant pas par 0, ou rien tant qu'une période suit
  • Une période suivie d'un ou plusieurs nombres
viande en pot
la source
4

Une valeur entière peut être vérifiée par:

function isNumeric(value) {
    var bool = isNaN(+value));
    bool = bool || (value.indexOf('.') != -1);
    bool = bool || (value.indexOf(",") != -1);
    return !bool;
};

De cette façon, c'est plus facile et plus rapide! Tous les tests sont vérifiés!

solidaire
la source
4

Voici une version légèrement améliorée (probablement le moyen le plus rapide) que j'utilise à la place de la variante exacte de jQuery, je ne sais vraiment pas pourquoi ils n'utilisent pas celui-ci:

function isNumeric(val) {
    return !isNaN(+val) && isFinite(val);
}

L'inconvénient de la version de jQuery est que si vous passez une chaîne avec des chiffres de début et des lettres de fin comme "123abc"le parseFloat | parseIntva extraire la fraction numérique et retourner 123, MAIS, le deuxième garde isFiniteéchouera quand même. Avec l' +opérateur unaire , il mourra sur le tout premier garde puisque + lance NaN pour de tels hybrides :) Un peu de performance pourtant je pense un solide gain sémantique.

Arman McHitarian
la source
2
Attention le '+' unaire invoquera valueOf () sur un objet - voir ce jsfiddle . Cela échoue également pour le premier espace, tout comme la réponse principale.
earcam
3

Ma solution,

function isNumeric(input) {
    var number = /^\-{0,1}(?:[0-9]+){0,1}(?:\.[0-9]+){0,1}$/i;
    var regex = RegExp(number);
    return regex.test(input) && input.length>0;
}

Cela semble fonctionner dans toutes les situations, mais je peux me tromper.

Manusoftar
la source
Ce regex serait moins déroutant si vous n'échappiez pas inutilement aux personnages, utilisez ?pour {0,1}et \dpour [0-9]. De plus +, puis en l'enveloppant (?:){0,1}, vous pouvez aussi utiliser *et oublier les groupes (non) capturés.
alex
3

J'utilise une solution plus simple:

function isNumber(num) {
    return parseFloat(num).toString() == num
}
Ali Gonabadi
la source
5
cela échouera sur quoi que ce soit avec des 0 superflus à la fin. exemple: "10.0"
Janus Troelsen
3

Cela devrait fonctionner. Certaines des fonctions fournies ici sont défectueuses et devraient également être plus rapides que toute autre fonction ici.

        function isNumeric(n)
        {
            var n2 = n;
            n = parseFloat(n);
            return (n!='NaN' && n2==n);
        }

Expliqué:

Créez une copie de lui-même, puis convertissez le nombre en flottant, puis comparez-le avec le nombre d'origine, s'il s'agit toujours d'un nombre (entier ou flottant), et correspond au nombre d'origine, c'est-à-dire qu'il s'agit bien d'un nombre.

Il fonctionne avec des chaînes numériques ainsi que des nombres simples. Ne fonctionne pas avec des nombres hexadécimaux.

Attention: utilisez à vos risques et périls, aucune garantie.

utilisateur532188
la source
4
utiliser à vos risques et périls, aucune garantie que je n'utiliserais pas de code dont l'auteur n'est pas sûr;)
alex
1
@Alex, Ayez au moins votre propre opinion sur les choses. Ne vous contentez pas de critiquer tout le temps.
Stewart Mbofana
3

Aucune des réponses ne renvoie falsepour les chaînes vides, un correctif pour cela ...

function is_numeric(n)
{
 return (n != '' && !isNaN(parseFloat(n)) && isFinite(n));
}
John
la source
3

Pour vérifier si une variable contient un nombre valide et pas seulement une chaîne qui ressemble à un nombre, Number.isFinite(value)peut être utilisée.

Cela fait partie du langage depuis ES2015

Exemples:

Number.isFinite(Infinity)   // false
Number.isFinite(NaN)        // false
Number.isFinite(-Infinity)  // false

Number.isFinite(0)          // true
Number.isFinite(2e64)       // true

Number.isFinite('0')        // false
Number.isFinite(null)       // false
adius
la source
1
Je suppose que beaucoup de gens se réfèrent à cette question pour analyser les entrées utilisateur, qui seront généralement une chaîne . Cette réponse échoue dans ces cas, comme vous l'énumérez correctement dans les exemples, par exempleNumber.isFinite('0') -> false
Michael Haren
Tu as tout à fait raison. J'ai essayé de clarifier ce front.
adius
3
function inNumeric(n){
   return Number(n).toString() === n;
}

Si n est numérique Number(n), la valeur numérique sera retournée et la toString()transformera en chaîne. Mais si n n'est pas numérique, Number(n)il reviendra NaNdonc il ne correspondra pas à l'originaln

chrmcpn
la source
Bien que cet extrait de code puisse résoudre la question, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code. Essayez également de ne pas surcharger votre code avec des commentaires explicatifs, car cela réduit la lisibilité du code et des explications!
Au revoir StackExchange
2

Je me rends compte que cela a été répondu plusieurs fois, mais ce qui suit est un candidat décent qui peut être utile dans certains scénarios.

il convient de noter qu'il suppose que «.42» n'est pas un nombre, et «4.» n'est PAS un nombre, il faut donc en tenir compte.

function isDecimal(x) {
  return '' + x === '' + +x;
}

function isInteger(x) {
  return '' + x === '' + parseInt(x);
}

Le isDecimalréussit le test suivant:

function testIsNumber(f) {
  return f('-1') && f('-1.5') && f('0') && f('0.42')
    && !f('.42') && !f('99,999') && !f('0x89f')
    && !f('#abcdef') && !f('1.2.3') && !f('') && !f('blah');
}

L'idée ici est que chaque nombre ou entier a une représentation de chaîne "canonique", et chaque représentation non canonique doit être rejetée. Donc, nous convertissons en nombre et en arrière, et voyons si le résultat est la chaîne d'origine.

L'utilité de ces fonctions dépend du cas d'utilisation. Une caractéristique est que les chaînes distinctes représentent des nombres distincts (si les deux réussissent le isNumber()test).

Cela est pertinent, par exemple pour les nombres comme noms de propriété d'objet.

var obj = {};
obj['4'] = 'canonical 4';
obj['04'] = 'alias of 4';
obj[4];  // prints 'canonical 4' to the console.
donquixote
la source
2

Fonctions de validation de la bibliothèque knockoutJs Inbuild

En l'étendant, le champ est validé

1) numéro

self.number = ko.observable(numberValue).extend ({nombre: vrai}) ;

Cas de test

numberValue = '0.0'    --> true
numberValue = '0'      --> true
numberValue = '25'     --> true
numberValue = '-1'     --> true
numberValue = '-3.5'   --> true
numberValue = '11.112' --> true
numberValue = '0x89f'  --> false
numberValue = ''       --> false
numberValue = 'sfsd'   --> false
numberValue = 'dg##$'  --> false

2) chiffre

self.number = ko.observable(numberValue).extend ({chiffre: vrai}) ;

Cas de test

numberValue = '0'      --> true
numberValue = '25'     --> true
numberValue = '0.0'    --> false
numberValue = '-1'     --> false
numberValue = '-3.5'   --> false
numberValue = '11.112' --> false
numberValue = '0x89f'  --> false
numberValue = ''       --> false
numberValue = 'sfsd'   --> false
numberValue = 'dg##$'  --> false

3) min et max

self.number = ko.observable(numberValue).extend ({min: 5}). extend ({max: 10}) ;

Ce champ accepte uniquement les valeurs comprises entre 5 et 10

Cas de test

numberValue = '5'    --> true
numberValue = '6'    --> true
numberValue = '6.5'  --> true
numberValue = '9'    --> true
numberValue = '11'   --> false
numberValue = '0'    --> false
numberValue = ''    --> false
nav0611
la source
2

Si vous devez valider un ensemble spécial de décimales, vous pouvez utiliser ce simple javascript:

http://codesheet.org/codesheet/x1kI7hAD

<input type="text" name="date" value="" pattern="[0-9]){1,2}(\.){1}([0-9]){2}" maxlength="6" placeholder="od npr.: 16.06" onchange="date(this);" />

Le Javascript:

function date(inputField) {        
  var isValid = /^([0-9]){1,2}(\.){1}([0-9]){2}$/.test(inputField.value);   
  if (isValid) {
    inputField.style.backgroundColor = '#bfa';
  } else {
    inputField.style.backgroundColor = '#fba';
  }
  return isValid;
}
studio-klik
la source
2

isNumeric=(el)=>{return Boolean(parseFloat(el)) && isFinite(el)}

Rien de bien différent mais on peut utiliser le constructeur booléen

Shishir Arora
la source