web-dev-qa-db-fra.com

(Intégré) manière en JavaScript pour vérifier si une chaîne est un nombre valide

J'espère qu'il y a quelque chose dans le même espace conceptuel que l'ancienne fonction IsNumeric() de VB6?

882
Electrons_Ahoy

Pour vérifier si une variable (y compris une chaîne) est un nombre, vérifiez si ce n'est pas un nombre:

Cela fonctionne que la variable contienne une chaîne ou un nombre.

isNaN(num)         // returns true if the variable does NOT contain a valid number

Exemples

isNaN(123)         // false
isNaN('123')       // false
isNaN('1e10000')   // false (This translates to Infinity, which is a number)
isNaN('foo')       // true
isNaN('10px')      // true

Bien sûr, vous pouvez le nier si vous en avez besoin. Par exemple, pour implémenter l'exemple IsNumeric que vous avez donné:

function isNumeric(num){
  return !isNaN(num)
}

Pour convertir une chaîne contenant un nombre en un nombre:

ne fonctionne que si la chaîne uniquement contient des caractères numériques, sinon elle retourne NaN.

+num               // returns the numeric value of the string, or NaN 
                   // if the string isn't purely numeric characters

Exemples

+'12'              // 12
+'12.'             // 12
+'12..'            // Nan
+'.12'             // 0.12
+'..12'            // Nan
+'foo'             // NaN
+'12px'            // NaN

Pour convertir une chaîne de manière lâche en un nombre

utile pour convertir '12px' en 12, par exemple:

parseInt(num)      // extracts a numeric value from the 
                   // start of the string, or NaN.

Exemples

parseInt('12')     // 12
parseInt('aaa')    // NaN
parseInt('12px')   // 12
parseInt('foo2')   // NaN      These last two may be different
parseInt('12a5')   // 12       from what you expected to see. 

Flotteurs

Gardez à l'esprit que, contrairement à +num, parseInt (comme son nom l'indique) convertira un float en entier en coupant tout ce qui suit le point décimal (si vous voulez utiliser parseInt()à cause de ce comportement, vous feriez probablement mieux d'utiliser une autre méthode à la place ):

+'12.345'          // 12.345
parseInt(12.345)   // 12
parseInt('12.345') // 12

Cordes vides

Les chaînes vides peuvent être un peu contre-intuitives. +num convertit les chaînes vides en zéro, et isNaN() suppose la même chose:

+''                // 0
isNaN('')          // false

Mais parseInt() n'est pas d'accord:

parseInt('')       // NaN
1841
Dan

Et vous pouvez aller dans le RegExp-way:

var num = "987238";

if(num.match(/^-{0,1}\d+$/)){
  //valid integer (positive or negative)
}else if(num.match(/^\d+\.\d+$/)){
  //valid float
}else{
  //not valid number
}
39
roenving

Si vous voulez vraiment vous assurer qu'une chaîne ne contient qu'un nombre, aucun nombre (entier ou virgule flottante) et exactement un nombre, vous ne pouvez pas utiliser parseInt()/parseFloat(), Number() ou !isNaN() par eux-mêmes. Notez que !isNaN() renvoie réellement true lorsque Number() renverra un nombre, et false lorsqu'il renverra NaN, je l'exclurai donc du reste de la discussion.

Le problème avec parseFloat() est qu’il renverra un nombre si la chaîne contient un nombre, même si la chaîne ne contient pas seulement et exactement un nombre:

parseFloat("2016-12-31")  // returns 2016
parseFloat("1-1") // return 1
parseFloat("1.2.3") // returns 1.2

Le problème avec Number() est qu’il retournera un nombre dans les cas où la valeur transmise n’est pas du tout un nombre!

Number("") // returns 0
Number(" ") // returns 0
Number(" \u00A0   \t\n\r") // returns 0

Le problème avec le roulement de votre propre regex est que, sauf si vous créez le regex exact pour faire correspondre un nombre à virgule flottante, car Javascript le reconnaît, vous allez rater des cas ou reconnaître des cas où vous ne devriez pas. Et même si vous pouvez créer votre propre regex, pourquoi? Il existe des méthodes intégrées plus simples pour le faire.

Cependant, il s'avère que Number() (et isNaN()) est la solution dans tous les cas où parseFloat() renvoie un nombre alors qu'il ne le devrait pas, et inversement. Donc, pour savoir si une chaîne est vraiment exacte et seulement un nombre, appelez les deux fonctions et voyez si elles les deux renvoient true:

function isNumber(str) {
  if (typeof str != "string") return false // we only process strings!
  // could also coerce to string: str = ""+str
  return !isNaN(str) && !isNaN(parseFloat(str))
}
27
Michael

Si vous essayez simplement de vérifier si une chaîne est un nombre entier (pas de décimales), regex est un bon choix. D'autres méthodes telles que isNaN sont trop compliquées pour quelque chose d'aussi simple.

function isNumeric(value) {
    return /^-{0,1}\d+$/.test(value);
}

console.log(isNumeric('abcd'));         // false
console.log(isNumeric('123a'));         // false
console.log(isNumeric('1'));            // true
console.log(isNumeric('1234567890'));   // true
console.log(isNumeric('-23'));          // true
console.log(isNumeric(1234));           // true
console.log(isNumeric('123.4'));        // false
console.log(isNumeric(''));             // false
console.log(isNumeric(undefined));      // false
console.log(isNumeric(null));           // false

Pour n'autoriser que les positifs les nombres entiers, utilisez ceci:

function isNumeric(value) {
    return /^\d+$/.test(value);
}

console.log(isNumeric('123'));          // true
console.log(isNumeric('-23'));          // false
26
Gavin

Essayez la fonction isNan :

La fonction isNaN () détermine si une valeur est un nombre illégal (Not-a-Number).

Cette fonction renvoie true si la valeur est égale à NaN. Sinon, il retourne faux.

Cette fonction est différente de la méthode spécifique à Number Number.isNaN () .

La fonction globale isNaN () convertit la valeur testée en nombre, puis la teste.

Number.isNan () ne convertit pas les valeurs en Number et ne renvoie pas true pour les valeurs autres que le type Number ...

20
theraccoonbear

Ancienne question, mais il manque plusieurs points dans les réponses données.

Notation scientifique.

!isNaN('1e+30') est true, mais dans la plupart des cas, lorsque les utilisateurs demandent des chiffres, ils ne souhaitent pas faire correspondre des éléments tels que 1e+30.

Les grands nombres flottants peuvent se comporter bizarrement

Observez (avec Node.js):

> var s = Array(16 + 1).join('9')
undefined
> s.length
16
> s
'9999999999999999'
> !isNaN(s)
true
> Number(s)
10000000000000000
> String(Number(s)) === s
false
>

D'autre part:

> var s = Array(16 + 1).join('1')
undefined
> String(Number(s)) === s
true
> var s = Array(15 + 1).join('9')
undefined
> String(Number(s)) === s
true
>

Donc, si on s'attend à String(Number(s)) === s, il vaut mieux limiter vos chaînes à 15 chiffres au plus (après avoir omis les zéros de tête).

Infinity

> typeof Infinity
'number'
> !isNaN('Infinity')
true
> isFinite('Infinity')
false
>

Compte tenu de tout cela, vérifiez que la chaîne donnée est un nombre satisfaisant à tous les critères suivants:

  • notation non scientifique
  • conversion prévisible en Number et retour en String
  • fini

ce n'est pas une tâche facile. Voici une version simple:

  function isNonScientificNumberString(o) {
    if (!o || typeof o !== 'string') {
      // Should not be given anything but strings.
      return false;
    }
    return o.length <= 15 && o.indexOf('e+') < 0 && o.indexOf('E+') < 0 && !isNaN(o) && isFinite(o);
  }

Cependant, même celui-ci est loin d'être complet. Les zéros en tête ne sont pas traités ici, mais ils nient le test de longueur.

10
mark

Peut-être y at-il une ou deux personnes qui rencontrent cette question et qui ont besoin d’un contrôle beaucoup plus strict que d’habitude (comme je l’ai fait). Dans ce cas, cela pourrait être utile:

if(str === String(Number(str))) {
  // it's a "perfectly formatted" number
}

Il faut se méfier! Cela rejettera des chaînes telles que .1, 40.000, 080, 00.1. C'est très difficile - la chaîne doit correspondre à la "forme minimale la plus minimale" du nombre pour que ce test réussisse.

Il utilise les constructeurs String et Number pour convertir la chaîne en un nombre, puis pour vérifier si la "forme minimale parfaite" du moteur JavaScript (celle dans laquelle il a été converti avec le constructeur initial Number) correspond à la chaîne d'origine.

6
user993683

La réponse acceptée à cette question présente de nombreux défauts (comme le soulignent quelques autres utilisateurs). C'est l'un des moyens les plus simples et éprouvés de l'aborder en javascript:

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

Voici quelques bons cas de test:

console.log(isNumeric(12345678912345678912)); // true
console.log(isNumeric('2 '));                 // true
console.log(isNumeric('-32.2 '));             // true
console.log(isNumeric(-32.2));                // true
console.log(isNumeric(undefined));            // false

// the accepted answer fails at these tests:
console.log(isNumeric(''));                   // false
console.log(isNumeric(null));                 // false
console.log(isNumeric([]));                   // false
6
Hamzeen Hameem

J'ai testé et la solution de Michael est la meilleure. Votez pour sa réponse ci-dessus (recherchez sur cette page "Si vous voulez vraiment vous assurer qu'une chaîne" pour la trouver). En substance, sa réponse est la suivante:

function isNumeric(num){
  num = "" + num; //coerce num to be a string
  return !isNaN(num) && !isNaN(parseFloat(num));
}

Cela fonctionne pour chaque cas de test, que j'ai documenté ici: https://jsfiddle.net/wggehvp9/5/

De nombreuses autres solutions échouent pour les cas Edge suivants: ' ', null, "", true et [] . En théorie, vous pouvez les utiliser, avec une gestion des erreurs appropriée, par exemple:

return !isNaN(num);

ou

return (+num === +num);

avec traitement spécial pour /\ s /, null, "" true, false, [] (et autres?)

5
JohnP2

parseInt (), mais sachez que cette fonction est un peu différente en ce sens qu'elle renvoie par exemple 100 pour parseInt ("100px").

5
liggett78

Eh bien, j'utilise celui que j'ai fabriqué ...

Cela a fonctionné jusqu'à présent:

function checkNumber(value) {
    if ( value % 1 == 0 )
    return true;
    else
    return false;
}

Si vous remarquez un problème, dites-le-moi, s'il vous plaît.

4
Rafael

Vous pouvez utiliser le résultat de Number lorsque vous passez un argument à son constructeur.

Si l'argument (une chaîne) ne peut pas être converti en nombre, il renvoie NaN. Vous pouvez donc déterminer si la chaîne fournie est un nombre valide ou non.

Remarques: Remarque: lorsque vous passez une chaîne vide ou '\t\t' et '\n\t', le nombre retournera 0; Passer vrai retournera 1 et faux retournera 0.

    Number('34.00') // 34
    Number('-34') // -34
    Number('123e5') // 12300000
    Number('123e-5') // 0.00123
    Number('999999999999') // 999999999999
    Number('9999999999999999') // 10000000000000000 (integer accuracy up to 15 digit)
    Number('0xFF') // 255
    Number('Infinity') // Infinity  

    Number('34px') // NaN
    Number('xyz') // NaN
    Number('true') // NaN
    Number('false') // NaN

    // cavets
    Number('    ') // 0
    Number('\t\t') // 0
    Number('\n\t') // 0
4
GibboK

Pourquoi l'implémentation de jQuery n'est-elle pas assez bonne?

function isNumeric(a) {
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0;
};

Michael suggéra quelque chose comme ceci (bien que j'ai volé la version modifiée de "user1691651 - John" ici):

function isNumeric(num){
    num = "" + num; //coerce num to be a string
    return !isNaN(num) && !isNaN(parseFloat(num));
}

Ce qui suit est une solution très probablement mauvaise performance, mais des résultats solides. Il s'agit d'un outil créé à partir de l'implémentation de jQuery 1.12.4 et de la réponse de Michael, avec une vérification supplémentaire des espaces de début/fin (car la version de Michael renvoie true pour les valeurs numériques comportant des espaces de début/fin):

function isNumeric(a) {
    var str = a + "";
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0 &&
           !/^\s+|\s+$/g.test(str) &&
           !isNaN(str) && !isNaN(parseFloat(str));
};

Cette dernière version a cependant deux nouvelles variables. On pourrait en contourner un, en faisant:

function isNumeric(a) {
    if ($.isArray(a)) return false;
    var b = a && a.toString();
    a = a + "";
    return b - parseFloat(b) + 1 >= 0 &&
            !/^\s+|\s+$/g.test(a) &&
            !isNaN(a) && !isNaN(parseFloat(a));
};

Je n'ai pas testé beaucoup de ces solutions, autrement que manuellement, en testant les quelques cas d'utilisation que je vais rencontrer avec ma situation actuelle, qui sont tous très classiques. Il s'agit d'une situation "debout sur les épaules des géants".

3

Citation:

isNaN (num) // renvoie true si la variable ne contient PAS un nombre valide

ce n'est pas tout à fait vrai si vous devez vérifier les espaces de début/fin, par exemple lorsqu'une certaine quantité de chiffres est requise et que vous devez indiquer, par exemple, «1111» et non «111» ou «111», par exemple, un PIN entrée.

Mieux vaut utiliser:

var num = /^\d+$/.test(num)
3
Siubear

J'aime la simplicité de ceci. 

Number.isNaN(Number(value))

Ce qui précède correspond à un langage Javascript standard, mais je l’utilise conjointement avec un TypeScript typeguard pour la vérification de type intelligente. Ceci est très utile pour que le compilateur TypeScript vous donne l'intellisense correct et aucune erreur de type.

TypeScriptguards

isNotNumber(value: string | number): value is string {
    return Number.isNaN(Number(this.smartImageWidth));
}
isNumber(value: string | number): value is number {
    return Number.isNaN(Number(this.smartImageWidth)) === false;
}

Disons que vous avez une propriété width qui est number | string. Vous voudrez peut-être faire la logique en fonction de savoir si c'est une chaîne.

var width: number|string;
width = "100vw";

if (isNotNumber(width)) 
{
    // the compiler knows that width here must be a string
    if (width.endsWith('vw')) 
    {
        // we have a 'width' such as 100vw
    } 
}
else 
{
    // the compiler is smart and knows width here must be number
    var doubleWidth = width * 2;    
}

Le typeguard est suffisamment intelligent pour contraindre le type de width dans l'instruction if à ONLY string. Cela permet au compilateur d'autoriser width.endsWith(...) qu'il n'autorisait pas si le type était string | number.

Vous pouvez appeler le typeguard comme vous voulez isNotNumber, isNumber, isString, isNotString mais je pense que isString est un peu ambigu et plus difficile à lire.

1
Simon_Weaver

Ma tentative d'un peu déroutant, Pherhaps pas la meilleure solution

function isInt(a){
    return a === ""+~~a
}


console.log(isInt('abcd'));         // false
console.log(isInt('123a'));         // false
console.log(isInt('1'));            // true
console.log(isInt('0'));            // true
console.log(isInt('-0'));           // false
console.log(isInt('01'));           // false
console.log(isInt('10'));           // true
console.log(isInt('-1234567890'));  // true
console.log(isInt(1234));           // true
console.log(isInt('123.4'));        // false
console.log(isInt(''));             // false

// other types then string returns false
console.log(isInt(5));              // false
console.log(isInt(undefined));      // false
console.log(isInt(null));           // false
console.log(isInt('0x1'));          // false
console.log(isInt(Infinity));       // false
1
Endless

PFB la solution de travail:

 function(check){ 
    check = check + "";
    var isNumber =   check.trim().length>0? !isNaN(check):false;
    return isNumber;
    }
1
Predhin

Si quelqu'un arrive aussi loin, j'ai passé du temps à essayer de corriger moment.js ( https://github.com/moment/moment ). Voici quelque chose que j'en ai tiré:

function isNumeric(val) {
    var _val = +val;
    return (val !== val + 1) //infinity check
        && (_val === +val) //Cute coercion check
        && (typeof val !== 'object') //Array/object check
}

Traite les cas suivants:

Vrai! :

isNumeric("1"))
isNumeric(1e10))
isNumeric(1E10))
isNumeric(+"6e4"))
isNumeric("1.2222"))
isNumeric("-1.2222"))
isNumeric("-1.222200000000000000"))
isNumeric("1.222200000000000000"))
isNumeric(1))
isNumeric(0))
isNumeric(-0))
isNumeric(1010010293029))
isNumeric(1.100393830000))
isNumeric(Math.LN2))
isNumeric(Math.PI))
isNumeric(5e10))

Faux! :

isNumeric(NaN))
isNumeric(Infinity))
isNumeric(-Infinity))
isNumeric())
isNumeric(undefined))
isNumeric('[1,2,3]'))
isNumeric({a:1,b:2}))
isNumeric(null))
isNumeric([1]))
isNumeric(new Date()))

Ironiquement, celui avec lequel je me bats le plus:

isNumeric(new Number(1)) => false

Toutes les suggestions sont les bienvenues. :]

1
The Dembinski
function isNumberCandidate(s) {
  const str = (''+ s).trim();
  if (str.length === 0) return false;
  return !isNaN(+str);
}

console.log(isNumberCandidate('1'));       // true
console.log(isNumberCandidate('a'));       // false
console.log(isNumberCandidate('000'));     // true
console.log(isNumberCandidate('1a'));      // false 
console.log(isNumberCandidate('1e'));      // false
console.log(isNumberCandidate('1e-1'));    // true
console.log(isNumberCandidate('123.3'));   // true
console.log(isNumberCandidate(''));        // false
console.log(isNumberCandidate(' '));       // false
console.log(isNumberCandidate(1));         // true
console.log(isNumberCandidate(0));         // true
console.log(isNumberCandidate(NaN));       // false
console.log(isNumberCandidate(undefined)); // false
console.log(isNumberCandidate(null));      // false
console.log(isNumberCandidate(-1));        // true
console.log(isNumberCandidate('-1'));      // true
console.log(isNumberCandidate('-1.2'));    // true
console.log(isNumberCandidate(0.0000001)); // true
console.log(isNumberCandidate('0.0000001')); // true
console.log(isNumberCandidate(Infinity));    // true
console.log(isNumberCandidate('Infinity'));  // true

if (isNumberCandidate(s)) {
  // use +s as a number
  +s ...
}
1
gvlax

Voici une version haute performance (2,5 * 10 ^ 7 itérations/s @ 3.8GHz Haswell) d'une implémentation isNumber. Cela fonctionne pour tous les tests que je pourrais trouver (y compris les symboles):

var isNumber = (function () {
  var isIntegerTest = /^\d+$/;
  var isDigitArray = [!0, !0, !0, !0, !0, !0, !0, !0, !0, !0];
  function hasLeading0s (s) {
    return !(typeof s !== 'string' ||
    s.length < 2 ||
    s[0] !== '0' ||
    !isDigitArray[s[1]] ||
    isIntegerTest.test(s));
  }
  var isWhiteSpaceTest = /\s/;
  return function isNumber (s) {
    var t = typeof s;
    var n;
    if (t === 'number') {
      return (s <= 0) || (s > 0);
    } else if (t === 'string') {
      n = +s;
      return !((!(n <= 0) && !(n > 0)) || n === '0' || hasLeading0s(s) || !(n !== 0 || !(s === '' || isWhiteSpaceTest.test(s))));
    } else if (t === 'object') {
      return !(!(s instanceof Number) || ((n = +s), !(n <= 0) && !(n > 0)));
    }
    return false;
  };
})();
0
c7x43t

Vous pouvez utiliser des types, comme avec la flow librar y, pour obtenir une vérification statique de la compilation. Bien sûr, pas très utile pour la saisie de l'utilisateur.

// @flow

function acceptsNumber(value: number) {
  // ...
}

acceptsNumber(42);       // Works!
acceptsNumber(3.14);     // Works!
acceptsNumber(NaN);      // Works!
acceptsNumber(Infinity); // Works!
acceptsNumber("foo");    // Error!
0
What Would Be Cool

Dans mon application, nous n'autorisons que les caractères a-z A-Z et 0-9. J'ai trouvé la réponse ci-dessus en utilisant "string% 1 === 0", sauf si la chaîne commençait par 0xnn (comme 0x10), puis le renverrait sous forme numérique lorsque nous ne le souhaitions pas. Le simple piège suivant dans ma vérification numérique semble faire l'affaire dans nos cas spécifiques. 

function isStringNumeric(str_input){   
    //concat a temporary 1 during the modulus to keep a beginning hex switch combination from messing us up   
    //very simple and as long as special characters (non a-z A-Z 0-9) are trapped it is fine   
    return '1'.concat(str_input) % 1 === 0;}

Attention : Cela pourrait exploiter un bogue de longue date en Javascript et Actionscript [Number ("1" + the_string)% 1 === 0)], je ne peux pas en parler, mais c'est exactement ce dont nous avions besoin .

0
rwheadon

J'ai récemment écrit un article sur les moyens de s'assurer qu'une variable est un nombre valide: https://github.com/jehugaleahsa/artifacts/blob/master/2018/TypeScript_num_hack.md L'article explique comment assurer la virgule flottante entier, si c'est important (+x vs ~~x).

L'article suppose que la variable est une string ou une number pour commencer et que trim est disponible/polyfilled. Il ne serait pas difficile de l'étendre à d'autres types. Voici la viande de celui-ci:

// Check for a valid float
if (x == null
    || ("" + x).trim() === ""
    || isNaN(+x)) {
    return false;  // not a float
}

// Check for a valid integer
if (x == null
    || ("" + x).trim() === ""
    || ~~x !== +x) {
    return false;  // not an integer
}
0
Travis Parks

Utilisez simplement isNaN(), cela convertira la chaîne en numéro et si vous obtenez un nombre valide, vous retournerez false...

isNaN("Alireza"); //return true
isNaN("123"); //return false
0
Alireza

J'utilise les éléments suivants:

const isNumber = s => !isNaN(+s)
0
haxpanel

Epargnez-vous la migraine d'essayer de trouver une solution "intégrée".

Il n'y a pas de bonne réponse, et la réponse énormément votée dans ce fil est fausse.

npm install is-number

En JavaScript, il n’est pas toujours aussi simple de vérifier de manière fiable si une valeur est un nombre. Il est courant que les développeurs utilisent +, - ou Number () pour convertir une valeur de chaîne en nombre (par exemple, lorsque les valeurs sont renvoyées à partir d'une entrée utilisateur, de correspondances de regex, d'analyseurs, etc.). Cependant, de nombreux cas Edge non intuitifs donnent des résultats inattendus:

console.log(+[]); //=> 0
console.log(+''); //=> 0
console.log(+'   '); //=> 0
console.log(typeof NaN); //=> 'number'
0
cdeutsch

Il n'est pas valide pour TypeScript en tant que:

declare function isNaN(number: number): boolean;

Pour TypeScript, vous pouvez utiliser:

/^\d+$/.test(key)

0
Greg Woz

Voici une ligne pour vérifier si sNum est une valeur numérique valide. il a été testé pour une grande variété d'entrées:

!isNaN(+s.replace(/\s|\$/g, ''));  // returns True if numeric value
0
lifebalance

Utilisation de JavaScript simple:

Number.isNaN(Number('1')); // false
Number.isNaN(Number('asdf')); // true

Utiliser Lodash:

_.isNaN(_.toNumber('1')); // false
_.isNaN(_.toNumber('asdf')); // true
0
Abtin Gramian

Ma solution:

// returns true for positive ints; 
// no scientific notation, hexadecimals or floating point dots

var isPositiveInt = function(str) { 
   var result = true, chr;
   for (var i = 0, n = str.length; i < n; i++) {
       chr = str.charAt(i);
       if ((chr < "0" || chr > "9") && chr != ",") { //not digit or thousands separator
         result = false;
         break;
       };
       if (i == 0 && (chr == "0" || chr == ",")) {  //should not start with 0 or ,
         result = false;
         break;
       };
   };
   return result;
 };

Vous pouvez ajouter des conditions supplémentaires dans la boucle pour répondre à vos besoins particuliers.

0
GoTo