Convalida numeri decimali in JavaScript - IsNumeric ()


2376

Qual è il modo più pulito ed efficace per convalidare i numeri decimali in JavaScript?

Punti bonus per:

  1. Chiarezza. La soluzione dovrebbe essere pulita e semplice.
  2. Cross-platform.

Casi 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

256
Solo una nota 99.999 è un numero valido in Francia, è lo stesso di 99.999 nel formato uk / us, quindi se stai leggendo in una stringa da dire un modulo di input allora 99.999 potrebbe essere vero.
Re0sless,

5
Dai un'occhiata anche a questo post e agli ottimi commenti .
Powtac,

79
La virgola decimale è lo standard in tutta Europa e Russia (tranne il Regno Unito)
Calmarius,

90
jQuery 1.7 ha introdotto la jQuery.isNumericfunzione di utilità: api.jquery.com/jQuery.isNumeric
Ates Goral

24
jQuery.isNumericfallirà il settimo caso di test del PO ( IsNumeric('0x89f') => *false*). Tuttavia, non sono sicuro di essere d'accordo con questo caso di test.
Tim Lehner,

Risposte:


2898

La risposta di Joel è abbastanza vicina, ma fallirà nei seguenti casi:

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

Qualche tempo fa ho dovuto implementare una IsNumericfunzione, per scoprire se una variabile conteneva un valore numerico, indipendentemente dal tipo , poteva essere un Stringvalore numerico contenente (dovevo considerare anche la notazione esponenziale, ecc.), Un Numberoggetto, praticamente qualsiasi cosa potrebbe essere passata a quella funzione, non ho potuto fare ipotesi di tipo, occupandomi della coercizione del tipo (es. +true == 1;ma truenon dovrei essere considerato "numeric").

Penso che valga la pena condividere questo set di +30 unit test effettuati su numerose implementazioni di funzioni e condividere anche quello che supera tutti i miei test:

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

PS isNaN e isFinite hanno un comportamento confuso a causa della conversione forzata in numero. In ES6, Number.isNaN e Number.isFinite risolverebbero questi problemi. Tienilo a mente quando li usi.


Aggiornamento : ecco come funziona jQuery (2.2-stable) :

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

Aggiornamento : Angolare 4.3 :

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

26
questo fallisce con altre localizzazioni in cui usiamo virgole decimali, ma aggiungi `n = n.replace (/, /,". "); ' prima del ritorno per risolverlo.
Zoltan Lengyel,

5
@RobG, quel comportamento è intenzionale, da 2e308 > Number.MAX_VALUEallora 2e308 == Infinity. Se si desidera una funzione che ritorni trueanche per valori di infinito positivi e negativi, controllare la funzione n. 2 nella suite di test . Saluti.
CMS,

39
A proposito, i test unitari vengono ora utilizzati dal progetto jQuery
CMS

7
jQuery ora utilizza anche questa implementazione.
RichardTowers,

4
La soluzione qui è semplicemente usare JQuery. Hanno un'implementazione ancora migliore di questo ora: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli,

337

Arrrgh! Non ascoltare le risposte dell'espressione regolare. RegEx è pazzo per questo, e non sto parlando solo di performance. È così facile fare errori sottili, impossibili da individuare con la tua espressione regolare.

Se non puoi usarlo isNaN(), dovrebbe funzionare molto meglio:

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

Ecco come funziona:

L' (input - 0)espressione forza JavaScript a fare la coercizione del tipo sul valore di input; deve prima essere interpretato come un numero per l'operazione di sottrazione. Se la conversione in un numero fallisce, l'espressione si tradurrà in NaN. Questo risultato numerico viene quindi confrontato con il valore originale che hai passato. Poiché il lato sinistro è ora numerico, il tipo coercizione viene nuovamente utilizzato. Ora che l'input da entrambi i lati è stato forzato nello stesso tipo dallo stesso valore originale, si potrebbe pensare che dovrebbero essere sempre gli stessi (sempre vero). Tuttavia, esiste una regola speciale che dice che NaNnon è mai uguale a NaN, e quindi un valore che non può essere convertito in un numero (e solo i valori che non possono essere convertiti in numeri) risulteranno falsi.

Il controllo sulla lunghezza è per un caso speciale che coinvolge stringhe vuote. Nota anche che cade nel tuo test 0x89f, ma è perché in molti ambienti è un modo corretto per definire un numero letterale. Se si desidera catturare quello specifico scenario, è possibile aggiungere un ulteriore controllo. Ancora meglio, se questo è il motivo per cui non si utilizza, isNaN()basta avvolgere la propria funzione isNaN()che può anche fare il controllo aggiuntivo.

In breve, se vuoi sapere se un valore può essere convertito in un numero, prova effettivamente a convertirlo in un numero.


Sono tornato indietro e ho fatto qualche ricerca sul perché una stringa di spazi bianchi non avesse l'output previsto, e penso di ottenerla ora: una stringa vuota viene forzata 0anziché NaN. Basta tagliare la corda prima del controllo della lunghezza per gestire questo caso.

L'esecuzione dei test unitari con il nuovo codice fallisce solo sui valori letterali booleani e infiniti, e l'unica volta che dovrebbe essere un problema è se stai generando codice (davvero, chi digiterebbe un valore letterale e verificherebbe se è numerico? Dovresti sapere ), e sarebbe un codice strano da generare.

Ma, ancora una volta, l'unico motivo per usarlo è se per qualche motivo devi evitare isNaN ().


28
Questo non riesce sulle stringhe di spazi bianchi, ad esempio IsNumeric(' '), IsNumeric('\n\t')ecc. Tutti ritornanotrue
Crescent Fresh il

29
Inoltre, i Numbervalori letterali non verranno IsNumeric(5) == false;controllati nel set di test unit che ho pubblicato, questa funzione è il numero 16nella suite di test. stackoverflow.com/questions/18082/…
CMS

20
Non riesco a credere che nessuno abbia sottolineato l'uso di un'espressione regolare (sostituisci) dopo aver avvertito di non usare espressioni regolari ... Certo, una sostituzione di spazi bianchi è più semplice di un'analisi numerica, ma è ancora sicuramente "maliziosa".
Patrick M,

1
@Oriol Questo è un grosso problema ... senza correzioni di sicurezza rilasciate dopo quella data, allontanarsi da XP dovrebbe essere una priorità.
Joel Coehoorn,

1
@Oriol XP o no, se si utilizza IE8 o versioni precedenti si sta utilizzando un software orribilmente obsoleto. XP concesso non può eseguire IE9 +, quindi usa Chrome o FF. Le persone che vivono in passato usando IE8 sono la rovina dell'esistenza di molti sviluppatori web. Se potessi avere indietro il tempo che ho trascorso assicurandomi che il codice perfettamente funzionante funzioni anche in IE8 ... Per me prendere il codice che funziona in FF e Chrome e correggerlo per eseguirlo in IE8 è altrettanto pratico prendere un eseguibile di Windows 8 e assicurandosi che funzioni allo stesso modo in Windows 3.1.
chiliNUT

70

In questo modo sembra funzionare bene:

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

In una riga:

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

E per testarlo:

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

Ho preso in prestito quel regex da http://www.codetoad.com/javascript/isnumeric.asp . Spiegazione:

/^ 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

1
// DOVREBBE ESSERE AGGIUNTI ANCHE ALLA PROVA risultati + = (! IsNumeric ('-')? "Pass": "Fail") + ": IsNumeric ('-') => false \ n"; risultati + = (! IsNumeric ('01 ')? "Pass": "Fail") + ": IsNumeric ('01') => false \ n"; risultati + = (! IsNumeric ('- 01')? "Pass": "Fail") + ": IsNumeric ('- 01') => false \ n"; risultati + = (! IsNumeric ('000')? "Pass": "Fail") + ": IsNumeric ('000') => false \ n";
Dan,

che cosa fa questo? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
call-me

"{0,1}" può essere sostituito con "?", quindi la tua regexp sarà simile a questa: /^-?\d*\.?\d+$/?
Cloud

bello e semplice.
-breaker

53

Yahoo! L'interfaccia utente utilizza questo:

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

25
Questo è più che controlla il tipo di variabile rispetto al contenuto del numero. Fallirà anche sui numeri creati con new Number(1).
alex,

4
Come dice alex, questo in realtà non risponde alla domanda posta poiché questo fallirà se o = "1001".
Caso

50
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

Funziona anche con numeri di tipo 0x23.


29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Tornare trueal posto di false.
Oriol,

49

La risposta accettata non ha superato il test n. 7 e suppongo sia perché hai cambiato idea. Quindi questa è una risposta alla risposta accettata, con la quale ho avuto problemi.

Durante alcuni progetti ho dovuto convalidare alcuni dati ed essere il più certo possibile che si tratti di un valore numerico javascript che può essere utilizzato in operazioni matematiche.

jQuery e alcune altre librerie javascript includono già tale funzione, di solito chiamata isNumeric. C'è anche un post su stackoverflow che è stato ampiamente accettato come risposta, la stessa routine generale che stanno utilizzando le librerie di cui sopra.

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

Innanzitutto, il codice sopra restituisce true se l'argomento era un array di lunghezza 1 e quel singolo elemento era di un tipo ritenuto numerico dalla logica precedente. Secondo me, se è un array, allora non è numerico.

Per alleviare questo problema, ho aggiunto un controllo per scartare gli array dalla logica

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

Naturalmente, si potrebbe anche usare Array.isArray, jQuery $.isArrayo un prototipo Object.isArray, invece diObject.prototype.toString.call(n) !== '[object Array]'

Il mio secondo problema era che le stringhe letterali intere esadecimali negative ("-0xA" -> -10) non venivano conteggiate come numeriche. Tuttavia, le stringhe letterali intere esadecimali positive ("0xA" -> 10) sono state trattate come numeriche. Avevo bisogno che entrambi fossero validi numerici.

Ho quindi modificato la logica per tenerne conto.

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

Se sei preoccupato per la creazione del regex ogni volta che viene chiamata la funzione, puoi riscriverlo in una chiusura, qualcosa del genere

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

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

Ho quindi preso casi di test CMS +30 e clonato il test su jsfiddle aggiunto i miei casi di test extra e la mia soluzione sopra descritta.

Potrebbe non sostituire la risposta ampiamente accettata / utilizzata ma se questo è più di quello che ti aspetti come risultati dalla tua funzione isNumeric, si spera che questo possa essere di qualche aiuto.

EDIT: Come sottolineato da Bergi , ci sono altri possibili oggetti che potrebbero essere considerati numerici e sarebbe meglio inserire nella whitelist che nella blacklist. Con questo in mente aggiungerei ai criteri.

Voglio che la mia funzione isNumeric consideri solo numeri o stringhe

Con questo in mente, sarebbe meglio usarlo

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(/^-/, ''));
}

Prova le soluzioni

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>


2
Questa è a mio avviso la funzione più protetta; l'ultimo. La risposta accettata copre probabilmente il 99,99% di tutti i casi, ma questa probabilmente ha il 100% di a) casi con un piccolo sovraccarico.
Samuel,

Hai dimenticato letteralmente "99.999" punto di dilatazione. È un numero valido in tutta l'Europa escluso il Regno Unito
Andrii Horda,

Non è stato dimenticato, non era qualcosa che consideravo un valore numerico nel senso dei numeri Javascript, affermava anche l'OPIsNumeric('99,999') => false
Xotic750

34

Sì, il built-in isNaN(object)sarà molto più veloce di qualsiasi analisi regex, perché è integrato e compilato, invece di essere interpretato al volo.

Sebbene i risultati siano leggermente diversi da quello che stai cercando ( provalo ):

                                              // 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

18

Utilizzare la funzione isNaN. Credo che se esegui il test !isNaN(yourstringhere)funziona bene per una di queste situazioni.


Nota
:! IsNaN

if (! (x == null || isNaN (x))) alert ("isNumeric"); // Ma questa soluzione accetta 0x40, quindi non è ancora quello che voleva l'operazione.
circa il

Nota che isNaN ("Infinity") === false, che probabilmente non è anche quello che vuoi (ma non accadrà nella vita reale).
Erik Hesselink,

16

Da jQuery 1.7, è possibile utilizzare 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

Basta notare che a differenza di quello che hai detto, 0x89fè un numero valido (hexa)


L'OP vuole un numero decimale valido , quindi jQuery isNumeric non è adatto. Inoltre fallisce per numeri molto grandi.
RobG

13

Può essere fatto senza RegExp come

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

5
Se stiamo usando ==, tornerà vero anche per i numeri presentati come stringhe. Quindi il "42" verrà conteggiato come numero valido nel caso di "==" e verrà considerato non valido nel caso di ===
Aquatic

questo ritorna vero su "-0.", "-.0", ".0" e "0."
Janus Troelsen,


8
return (input - 0) == input && input.length > 0;

non ha funzionato per me. Quando ho messo un avviso e testato, è input.lengthstato undefined. Penso che non ci siano proprietà per controllare la lunghezza dei numeri interi. Quindi quello che ho fatto è stato

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

Ha funzionato bene.


7

Se non sbaglio, questo dovrebbe corrispondere a qualsiasi valore di numero JavaScript valido, escluse le costanti ( Infinity, NaN) e gli operatori dei segni +/ -(poiché in realtà non fanno parte del numero per quanto mi riguarda, sono operatori separati):

Ne avevo bisogno per un tokenizer, in cui l'invio del numero a JavaScript per la valutazione non era un'opzione ... Non è sicuramente l'espressione regolare più breve possibile, ma credo che catturi tutte le sottigliezze più fini della sintassi dei numeri di 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

I numeri validi includono:

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

I numeri non validi sarebbero

 - 00e1
 - 01e1
 - 00.0
 - 00x0
 - .
 - .e0

7

L'unico problema che ho avuto con la risposta di @ CMS è l'esclusione di NaNInfinity, che sono numeri utili per molte situazioni. Un modo per verificare la presenza di NaNè quello di verificare la presenza di valori numerici che non si eguagliano da soli NaN != NaN,! Quindi ci sono davvero 3 test che vorresti affrontare ...

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 è abbastanza vicino a un'altra risposta elegante , ma gestisce rappresentazioni di numeri esadecimali e di altre stringhe.


6

Per me, questo è il modo migliore:

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

Sfortunatamente, questo è un tipo di controllo numerico STRICT che fallirà per qualsiasi stringa contenente solo lettere numeriche, come "0" ecc ...
Arman McHitarian

6

Vorrei aggiungere quanto segue:

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

I numeri esadecimali positivi iniziano con 0xe i numeri esadecimali negativi iniziano con -0x. I numeri di ott positivi iniziano con 0e i numeri di ott negativi iniziano con -0. Questo prende in considerazione gran parte di ciò che è già stato menzionato, ma include numeri esadecimali e ottali, negativo scientifico, Infinito e ha rimosso il decimale scientifico ( 4e3.2non valido).

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

6

Penso che la funzione parseFloat possa fare tutto il lavoro qui. La funzione seguente supera tutti i test in questa pagina, tra cui isNumeric(Infinity) == true:

function isNumeric(n) {

    return parseFloat(n) == n;
}

Sì, sono giunto anche a questa conclusione. Mi piace anche il modo in cui gli array vengono trattati con questo metodo; un array con un singolo valore conta come quel valore, ma tutto il resto fallisce: IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; Ma immagino che sia una questione di gusti!
Mark Birbeck,

4

Un paio di test da aggiungere:

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

Ho pensato a questo:

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

La soluzione copre:

  • Un segno negativo facoltativo all'inizio
  • Un singolo zero, o una o più cifre che non iniziano con 0, o niente fino a quando segue un punto
  • Un periodo seguito da 1 o più numeri

4

Un valore intero può essere verificato da:

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

In questo modo è più facile e veloce! Tutti i test sono controllati!


4

Ecco una versione leggermente migliorata (probabilmente la via più veloce là fuori) che uso al posto dell'esatta variante di jQuery, davvero non so perché non usano questo:

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

Il rovescio della medaglia della versione di jQuery è che se si passa una stringa con numeri numerici iniziali e lettere finali come "123abc"quella parseFloat | parseIntestrarrà la frazione numerica e restituirà 123, MA, la seconda guardia isFinitefallirà comunque. Con l' +operatore unario morirà alla prima guardia poiché + lancia NaN per tali ibridi :) Una piccola prestazione, ma penso che un solido guadagno semantico.


2
Fai attenzione all'unario '+' che invocherà valueOf () su un oggetto - vedi questo jsfiddle . Anche questo fallisce anche per i principali spazi bianchi, così come la risposta principale.
earcam

3

La mia soluzione

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

Sembra funzionare in ogni situazione, ma potrei sbagliarmi.


Quella regex sarebbe meno confusa se non sfuggissi inutilmente ai personaggi, usa ?per {0,1}e \dper [0-9]. Inoltre, +quindi avvolgendolo con (?:){0,1}, puoi anche usare *e dimenticare i gruppi (non) di acquisizione.
alex,

3

Sto usando una soluzione più semplice:

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

5
questo fallirà su qualsiasi cosa con 0 superflui alla fine. esempio: "10.0"
Janus Troelsen,

3

Questo dovrebbe funzionare. Alcune delle funzioni fornite qui sono imperfette, inoltre dovrebbero essere più veloci di qualsiasi altra funzione qui.

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

Ha spiegato:

Crea una copia di se stesso, quindi converte il numero in float, quindi si confronta con il numero originale, se è ancora un numero (intero o float) e corrisponde al numero originale, ciò significa che è effettivamente un numero.

Funziona con stringhe numeriche e numeri semplici. Non funziona con numeri esadecimali.

Avvertenza: utilizzare a proprio rischio, nessuna garanzia.


4
utilizzare a proprio rischio, nessuna garanzia Non utilizzare codice di cui l'autore non è fiducioso;)
alex

1
@Alex, almeno hai la tua opinione sulle cose. Non solo criticare tutto il tempo.
Stewart Mbofana,

3

Nessuna delle risposte restituisce falsestringhe vuote, una correzione per quello ...

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

3

Per verificare se una variabile contiene un numero valido e non solo una stringa che assomiglia a un numero, è Number.isFinite(value)possibile utilizzare.

Questo fa parte del linguaggio dall'ES2015

Esempi:

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

1
Immagino che molte persone facciano riferimento a questa domanda per analizzare l'input dell'utente, che in genere sarà una stringa . Questa risposta fallisce in questi casi, come elencato correttamente negli esempi, ad esempioNumber.isFinite('0') -> false
Michael Haren,

Hai perfettamente ragione. Ho cercato di chiarire questo fronte.
adius,

3
function inNumeric(n){
   return Number(n).toString() === n;
}

Se n è numerico Number(n)restituirà il valore numerico e toString()lo trasformerà in una stringa. Ma se n non è numerico, Number(n)verrà restituito in NaNmodo che non corrisponda all'originalen


Sebbene questo frammento di codice possa risolvere la domanda, inclusa una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che in futuro stai rispondendo alla domanda dei lettori e che queste persone potrebbero non conoscere i motivi del tuo suggerimento sul codice. Cerca anche di non aggiungere il tuo codice a commenti esplicativi, in quanto ciò riduce la leggibilità sia del codice che delle spiegazioni!
Arrivederci StackExchange l'

2

Mi rendo conto che è stato risposto più volte, ma quanto segue è un candidato decente che può essere utile in alcuni scenari.

va notato che presuppone che ".42" NON sia un numero e "4." NON è un numero, quindi questo dovrebbe essere preso in considerazione.

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

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

Il isDecimalpassa il seguente test:

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'idea qui è che ogni numero o intero ha una rappresentazione di stringa "canonica" e ogni rappresentazione non canonica dovrebbe essere respinta. Quindi eseguiamo il cast su un numero e viceversa e vediamo se il risultato è la stringa originale.

Se queste funzioni sono utili per te dipende dal caso d'uso. Una caratteristica è che stringhe distinte rappresentano numeri distinti (se entrambi superano il isNumber()test).

Ciò è rilevante, ad esempio, per i numeri come nomi di proprietà dell'oggetto.

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

2

knockoutJs Funzioni di convalida della libreria Inbuild

Estendendolo, il campo viene convalidato

1) numero

self.number = ko.observable(numberValue).extend ({numero: vero}) ;

TestCase

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) cifra

self.number = ko.observable(numberValue).extend ({digit: true}) ;

TestCase

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 e max

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

Questo campo accetta solo valori compresi tra 5 e 10

TestCase

numberValue = '5'    --> true
numberValue = '6'    --> true
numberValue = '6.5'  --> true
numberValue = '9'    --> true
numberValue = '11'   --> false
numberValue = '0'    --> false
numberValue = ''    --> false

2

Se è necessario convalidare un set speciale di decimali y è possibile utilizzare questo semplice 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);" />

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

2

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

Niente di molto diverso, ma possiamo usare il costruttore booleano

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.