Question

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 tests :

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
Était-ce utile?

La solution

La réponse de @Joel est assez proche, mais il é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û mettre en œuvre un IsNumeric fonction, pour savoir si une variable contenait une valeur numérique, quel que soit son type, ça pourrait être un String contenant une valeur numérique (j'ai dû aussi considérer la notation exponentielle, etc.), un Number objet, pratiquement tout pouvait être transmis à cette fonction, je ne pouvais faire aucune hypothèse de type, en prenant soin de la coercition de type (par exemple. +true == 1; mais true ne devrait pas être considéré comme "numeric").

Je pense que cela vaut la peine de partager cet ensemble de +30 tests unitaires fait à de nombreuses implémentations de fonctions, et partage également celle qui réussit tous mes tests :

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

P.S. estNaN & est Fini ont un comportement déroutant en raison de la conversion forcée en nombre.Dans ES6, Numéro.isNaN & Nombre.isFinite résoudrait ces problèmes.Gardez cela à l’esprit lorsque vous les utilisez.


Mise à jour : Voici comment jQuery procède maintenant (2.2-stable):

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

Mise à jour : Angulaire 4.3:

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}

Autres conseils

Arrrgh!N'écoutez pas les réponses des expressions régulières.RegEx est dégoûtant pour ça, et je ne parle pas seulement de performances.Il est si facile de commettre des erreurs subtiles et impossibles à repérer 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).trim().length > 0;
}

Voici comment cela fonctionne:

Le (input - 0) l'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 nombre échoue, l'expression entraînera NaN.Ce numérique Le résultat est ensuite comparé à la valeur d'origine que vous avez transmise.Puisque le côté gauche est désormais numérique, la coercition de type est à nouveau utilisée.Maintenant que les entrées des deux côtés ont été contraintes au même type à partir de la même valeur d'origine, on pourrait penser qu'elles devraient toujours être les mêmes (toujours vraies).Cependant, il existe une règle spéciale qui dit NaN n'est jamais égal à NaN, et donc une valeur qui ne peut pas être convertie en nombre (et uniquement les valeurs qui ne peuvent pas être converties en nombres) entraînera false.

La vérification de la longueur concerne un cas particulier impliquant des chaînes vides.Notez également que cela échoue lors de votre test 0x89f, mais c'est parce que dans de nombreux environnements, c'est un bon moyen de définir un nombre littéral.Si vous souhaitez détecter ce scénario spécifique, vous pouvez ajouter une vérification supplémentaire.Encore mieux, si c'est la raison pour laquelle vous ne l'utilisez pas isNaN() alors enveloppez simplement votre propre fonction isNaN() cela peut également faire la vérification supplémentaire.

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


J'y suis retourné et j'ai fait quelques recherches pour pourquoi une chaîne d'espaces n'a pas eu le résultat attendu, et je pense que je comprends maintenant :une chaîne vide est contrainte à 0 plutôt que NaN.Il suffit de couper la corde avant la vérification de la longueur pour résoudre ce cas.

L'exécution des tests unitaires sur le nouveau code échoue uniquement sur les littéraux infinis et booléens, et le seul cas où cela devrait poser un problème est si vous générez du code (en réalité, qui saisirait un littéral et vérifierait s'il est numérique ?Tu devrais savoir), et ce serait un code étrange à générer.

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

Cette méthode 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 regex à 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

Yahoo!Interface utilisateur utilise ceci :

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

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

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'agissait d'une valeur numérique javascript pouvant ê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 y a aussi publier sur stackoverflow cela a été largement accepté comme réponse, la même routine générale que celle utilisée par les bibliothèques mentionnées ci-dessus.

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

Premièrement, le code ci-dessus renverrait 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 écarter 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 $.isArray ou prototype Object.isArray au lieu de Object.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) étaient traitées comme des valeurs numériques.J'avais besoin que les deux soient des chiffres valides.

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 de la création de l'expression régulière à chaque fois que la fonction est appelée, 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 CMS +30 cas de tests et cloné le test sur jsfiddle ajouté mes cas de test supplémentaires et ma solution décrite ci-dessus.

Cela ne remplace peut-être pas la réponse largement acceptée/utilisée, mais si cela correspond davantage à ce que vous attendez comme résultats de votre fonction isNumeric, j'espère que cela vous sera utile.

MODIFIER: 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 les mettre sur liste blanche plutôt que sur liste noire.Dans cet esprit, j'ajouterais aux critères.

Je veux que ma fonction isNumeric ne prenne en compte que 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>

Ouais, le intégré isNaN(object) sera beaucoup plus rapide que n'importe quelle analyse d'expression régulière, car elle est intégrée et compilée, au lieu d'être interprétée à 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

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

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, 0x89f est un nombre valide (hexa)

Cela peut être fait sans RegExp car

function IsNumeric(data){
    return parseFloat(data)==data;
}

Je me rends compte que la question initiale ne mentionnait pas jQuery, mais si vous utilisez jQuery, vous pouvez faire :

$.isNumeric(val)

Simple.

https://api.jquery.com/jQuery.isNumeric/ (à partir de jQuery 1.7)

Si je ne me trompe pas, cela devrait correspondre à n'importe quelle valeur numérique JavaScript valide, à l'exclusion des constantes (Infinity, NaN) et les opérateurs de signes +/- (car ils ne font pas réellement partie du numéro 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'elle saisit toutes les subtilités 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 incluent :

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

Des numéros invalides seraient

 - 00e1
 - 01e1
 - 00.0
 - 00x0
 - .
 - .e0
return (input - 0) == input && input.length > 0;

n'a pas fonctionné pour moi.Quand j'ai lancé une alerte et testé, input.length était undefined.Je pense qu'il n'existe aucune propriété permettant de vérifier la longueur entière.Alors ce que j'ai fait, c'est

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

Cela a bien fonctionné.

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

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

Seul problème que j'ai eu avec @CMS répondre est l'exclusion de NaN et Infinity, qui sont des nombres utiles dans de nombreuses situations.Une façon de vérifier NaNest de vérifier les valeurs numériques qui ne sont pas égales à elles-mêmes, NaN != NaN!Il y a donc vraiment 3 tests que vous aimeriez aborder...

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

Mon isComparableNumber est assez proche d'un autre élégant répondre, mais gère les représentations hexadécimales et autres représentations sous forme de chaîne de nombres.

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;
};

Cette méthode est plus simple et plus rapide !Tous les tests sont vérifiés !

Voici une version un peu 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 n'utilisent-ils pas celle-ci :

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

L'inconvénient de la version de jQuery est que si vous transmettez une chaîne avec des chiffres de début et des lettres de fin comme "123abc" le parseFloat | parseInt extraira la fraction numérique et renverra 123, MAIS, la deuxième garde isFinite ça échouera de toute façon.Avec l'unaire + l’opérateur il mourra sur la toute première garde puisque + jette NaN pour de tels hybrides :) Un peu de performance mais je pense qu’il s’agit d’un gain sémantique solide.

J'aimerais ajouter ce qui suit :

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

Les nombres hexadécimaux positifs commencent par 0x et les nombres hexadécimaux négatifs commencent par -0x.Les nombres d'octobre positifs commencent par 0 et les nombres d'octobre négatifs commencent par -0.Celui-ci prend en considération la plupart de ce qui a déjà été mentionné, mais inclut les nombres hexadécimaux et octaux, les nombres scientifiques négatifs, l'infini et a supprimé les nombres scientifiques décimaux (4e3.2 n'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));
}

Quelques tests à ajouter :

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

J'ai trouvé ça :

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'un point suit
  • Un point suivi d'un ou plusieurs chiffres

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.

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 float, puis se compare au nombre d'origine, s'il s'agit toujours d'un nombre (qu'il soit entier ou flottant), et correspond au nombre d'origine, cela signifie qu'il s'agit bien d'un nombre.

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

Avertissement:utilisez à vos propres risques, aucune garantie.

Aucune des réponses ne revient false pour les chaînes vides, un correctif pour ça...

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

Pour vérifier si une variable contient un nombre valide et non juste une chaîne de caractères qui ressemble à un nombre, Number.isFinite(value) peut être utilisé.

Cela fait partie du langage depuisES2015

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

J'utilise une solution plus simple :

function isNumber(num) {
    return parseFloat(num).toString() == num
}

Je me rends compte que cette question a reçu plusieurs réponses, 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, donc cela doit être pris en compte.

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

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

Le isDecimal ré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 sous forme de chaîne « canonique » et que toute représentation non canonique doit être rejetée.Nous convertissons donc en un nombre et inversement, 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 des chaînes distinctes représentent des nombres distincts (si les deux réussissent le isNumber() test).

Ceci est pertinent, par ex.pour les nombres comme noms de propriétés d'objet.

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

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 :dix});

Ce champ accepte uniquement des 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

Vous pouvez minimiser cette fonction de nombreuses manières, et vous pouvez également l'implémenter avec une expression régulière personnalisée pour les valeurs négatives ou des graphiques personnalisés :

$('.number').on('input',function(){
    var n=$(this).val().replace(/ /g,'').replace(/\D/g,'');
    if (!$.isNumeric(n))
        $(this).val(n.slice(0, -1))
    else
        $(this).val(n)
});
function inNumeric(n){
   return Number(n).toString() === n;
}

Si n est numérique Number(n) renverra la valeur numérique et toString() le transformera en chaîne.Mais si n n'est pas numérique Number(n) reviendra NaN donc ça ne correspondra pas à l'original n

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

function isNumeric(n) {

    return parseFloat(n) == n;
}

Réponse de @CMS:Votre extrait a échoué dans les cas d'espaces sur ma machine à l'aide de nodejs.Je l'ai donc combiné avecLa réponse de @joel aux éléments suivants :

is_float = function(v) {
    return !isNaN(v) && isFinite(v) &&
        (typeof(v) == 'number' || v.replace(/^\s+|\s+$/g, '').length > 0);
}

Je l'ai testé avec les cas qui sont des flotteurs :

var t = [
        0,
        1.2123,
        '0',
        '2123.4',
        -1,
        '-1',
        -123.423,
        '-123.432',
        07,
        0xad,
        '07',
        '0xad'
    ];

et les cas qui ne sont pas des flottants (y compris les espaces vides et les objets/tableaux) :

    var t = [
        'hallo',
        [],
        {},
        'jklsd0',
        '',
        "\t",
        "\n",
        ' '
    ];

Tout fonctionne comme prévu ici.Peut-être que cela aide.

Le code source complet pour cela peut être trouvé ici.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top