Überprüfen Sie Dezimalzahlen in JavaScript - IsNumeric ()


2376

Was ist der sauberste und effektivste Weg, um Dezimalzahlen in JavaScript zu validieren?

Bonuspunkte für:

  1. Klarheit. Die Lösung sollte sauber und einfach sein.
  2. Plattformübergreifend.

Testfälle:

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
Nur eine Notiz 99.999 ist eine gültige Zahl in Frankreich. Sie entspricht 99.999 im UK / US-Format. Wenn Sie also eine Zeichenfolge aus einem Eingabeformular einlesen, sind 99.999 möglicherweise wahr.
Re0sless


79
Dezimalkomma ist der Standard in ganz Europa und Russland (außer Großbritannien)
Calmarius

90
jQuery 1.7 hat die jQuery.isNumericUtility-Funktion eingeführt: api.jquery.com/jQuery.isNumeric
Ates Goral

24
jQuery.isNumericwird den siebten Testfall des OP nicht bestehen ( IsNumeric('0x89f') => *false*). Ich bin mir jedoch nicht sicher, ob ich diesem Testfall zustimme.
Tim Lehner

Antworten:


2898

@ Joels Antwort ist ziemlich nah, aber sie wird in den folgenden Fällen fehlschlagen:

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

Vor einiger Zeit musste ich eine IsNumericFunktion implementieren , um herauszufinden, ob eine Variable einen numerischen Wert enthielt, unabhängig von ihrem Typ , es könnte sich um Stringeinen numerischen Wert handeln (ich musste auch die Exponentialschreibweise usw. berücksichtigen), ein NumberObjekt, An diese Funktion konnte praktisch alles übergeben werden, ich konnte keine Typannahmen treffen und mich um den Typzwang kümmern (z. B. sollte +true == 1;aber truenicht als betrachtet werden "numeric").

Ich denke, es lohnt sich, diesen Satz von +30 Komponententests für zahlreiche Funktionsimplementierungen zu teilen und auch den zu teilen, der alle meine Tests besteht:

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

PS isNaN & isFinite verhalten sich aufgrund der erzwungenen Konvertierung in Zahlen verwirrend. In ES6 würde Number.isNaN & Number.isFinite diese Probleme beheben. Denken Sie daran, wenn Sie sie verwenden.


Update : So macht es jQuery jetzt (2.2-stabil) :

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

Update : Angular 4.3 :

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

26
Dies schlägt bei anderen Gebietsschemas fehl, in denen wir Dezimalkommas verwenden, aber `n = n.replace (/, /,". ") hinzufügen. ' vor der Rückkehr, um es zu beheben.
Zoltan Lengyel

5
@RobG, dieses Verhalten ist beabsichtigt, 2e308 > Number.MAX_VALUEda 2e308 == Infinity. Wenn Sie eine Funktion wünschen, die trueauch positive und negative Unendlichkeitswerte zurückgibt , überprüfen Sie die Funktion Nr. 2 in der Testsuite . Prost.
CMS

39
Übrigens werden die Unit-Tests jetzt vom jQuery-Projekt verwendet
CMS

7
jQuery ist jetzt auch mit dieser Implementierung.
RichardTowers

4
Die Lösung besteht darin, nur JQuery zu verwenden. Sie haben jetzt eine noch bessere Implementierung: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli

337

Arrrgh! Hören Sie nicht auf die Antworten mit regulären Ausdrücken. RegEx ist dafür eklig, und ich spreche nicht nur von Leistung. Es ist so einfach, subtile Fehler zu machen, die mit Ihrem regulären Ausdruck nicht zu erkennen sind.

Wenn Sie nicht verwenden können isNaN(), sollte dies viel besser funktionieren:

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

So funktioniert das:

Der (input - 0)Ausdruck zwingt JavaScript, einen Typzwang für Ihren Eingabewert auszuführen. Es muss zuerst als Zahl für die Subtraktionsoperation interpretiert werden. Wenn diese Konvertierung in eine Zahl fehlschlägt, führt der Ausdruck zu NaN. Dieses numerische Ergebnis wird dann mit dem ursprünglich übergebenen Wert verglichen. Da die linke Seite jetzt numerisch ist, wird erneut der Typ Zwang verwendet. Nachdem die Eingabe von beiden Seiten aus demselben ursprünglichen Wert auf denselben Typ gezwungen wurde, würden Sie denken, dass sie immer gleich sein sollten (immer wahr). Es gibt jedoch eine spezielle Regel, die besagt, dass NaNniemals gleich ist. NaNDaher führt ein Wert, der nicht in eine Zahl konvertiert werden kann (und nur Werte, die nicht in Zahlen konvertiert werden können), zu false.

Die Überprüfung der Länge gilt für einen Sonderfall mit leeren Zeichenfolgen. Beachten Sie auch, dass dies bei Ihrem 0x89f-Test nicht der Fall ist. In vielen Umgebungen ist dies jedoch eine gute Möglichkeit, ein Zahlenliteral zu definieren. Wenn Sie dieses spezielle Szenario erfassen möchten, können Sie eine zusätzliche Prüfung hinzufügen. Noch besser, wenn dies Ihr Grund für die isNaN()Nichtverwendung ist, wickeln Sie einfach Ihre eigene Funktion um isNaN(), die auch die zusätzliche Überprüfung durchführen kann.

Zusammenfassend kann , wenn Sie wissen wollen , ob ein Wert in eine Zahl umgewandelt werden, tatsächlich versuchen , es in eine Zahl zu konvertieren.


Ich ging zurück und recherchierte, warum eine Whitespace-Zeichenfolge nicht die erwartete Ausgabe hatte, und ich glaube, ich verstehe sie jetzt: Eine leere Zeichenfolge wird 0eher dazu gezwungen als NaN. Durch einfaches Trimmen der Zeichenfolge vor der Längenprüfung wird dieser Fall behandelt.

Wenn Sie die Unit-Tests mit dem neuen Code ausführen, schlägt dies nur für die Infinity- und Booleschen Literale fehl. Das einzige Problem, das auftreten sollte, ist, wenn Sie Code generieren (wer würde wirklich ein Literal eingeben und prüfen, ob es numerisch ist? Sie sollten es wissen ), und das wäre ein seltsamer Code, den Sie generieren müssen.

Aber noch einmal, der einzige Grund , dies jemals zu verwenden ist , wenn Sie aus irgendeinem Grund isNaN vermeiden müssen ().


28
Dies scheitert auf Leerzeichen Strings, zB IsNumeric(' '), IsNumeric('\n\t')usw. alle zurücktrue
Crescent Frisch

29
Es wird auch bei NumberLiteralen fehlschlagen. IsNumeric(5) == false;Überprüfen Sie die von mir veröffentlichten Komponententests. Diese Funktion ist die Nummer 16in der Testsuite. stackoverflow.com/questions/18082/…
CMS

20
Ich kann nicht glauben, dass niemand auf die Verwendung eines regulären Ausdrucks (Ersetzen) hingewiesen hat, nachdem er gewarnt hatte, keine regulären Ausdrücke zu verwenden ... Zugegeben, ein Ersetzen durch Leerzeichen ist einfacher als eine Zahlenanalyse, aber es ist definitiv "eklig".
Patrick M

1
@Oriol Das ist ein großes Problem ... da nach diesem Datum keine Sicherheitsupdates veröffentlicht wurden, sollte es eine Priorität sein, sich von XP zu entfernen.
Joel Coehoorn

1
@Oriol XP oder nicht, wenn Sie IE8 oder niedriger verwenden, verwenden Sie schrecklich veraltete Software. Zugegeben, XP kann IE9 + nicht ausführen. Verwenden Sie daher Chrome oder FF. Menschen, die in der Vergangenheit mit IE8 gelebt haben, sind der Fluch vieler Webentwickler. Wenn ich die Zeit zurückbekommen könnte, die ich damit verbracht habe, sicherzustellen, dass einwandfreier Code auch in IE8 ausgeführt wird ... Für mich ist es ungefähr so ​​praktisch, Code, der in FF und Chrome funktioniert, zu patchen, um ihn in IE8 auszuführen, und eine ausführbare Windows 8-Datei zu verwenden Stellen Sie sicher, dass es in Windows 3.1 gleich läuft.
ChiliNUT

70

Dieser Weg scheint gut zu funktionieren:

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

In einer Zeile:

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

Und um es zu testen:

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

Ich habe diesen regulären Ausdruck von http://www.codetoad.com/javascript/isnumeric.asp ausgeliehen . Erläuterung:

/^ 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
// SOLLTE AUCH ZU IHREN TESTERGEBNISSEN HINZUGEFÜGT WERDEN + = (! IsNumeric ('-')? "Pass": "Fail") + ": IsNumeric ('-') => false \ n"; Ergebnisse + = (! IsNumeric ('01 ')? "Pass": "Fail") + ": IsNumeric ('01') => false \ n"; Ergebnisse + = (! IsNumeric ('- 01')? "Pass": "Fail") + ": IsNumeric ('- 01') => false \ n"; Ergebnisse + = (! IsNumeric ('000')? "Pass": "Fail") + ": IsNumeric ('000') => false \ n";
Dan

Was macht das? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
Ruf mich

Kann "{0,1}" durch "?" ersetzt werden, sodass Ihr regulärer Ausdruck folgendermaßen aussieht: /^-?\d*\.?\d+$/?
Wolke

schön und einfach.
-Breaker

53

Yahoo! Die Benutzeroberfläche verwendet Folgendes:

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

25
Das bedeutet mehr, den Variablentyp zu überprüfen als den Inhalt der Nummer. Es schlägt auch bei Nummern fehl, die mit erstellt wurden new Number(1).
Alex

4
Wie Alex sagt, beantwortet dies die gestellte Frage nicht wirklich, da dies fehlschlagen wird, wenn o = "1001".
Fall

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

Dies funktioniert auch für 0x23-Typennummern.


29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Zurückkehren truestatt false.
Oriol

49

Die akzeptierte Antwort hat Ihren Test Nr. 7 nicht bestanden, und ich denke, das liegt daran, dass Sie Ihre Meinung geändert haben. Dies ist also eine Antwort auf die akzeptierte Antwort, mit der ich Probleme hatte.

Während einiger Projekte musste ich einige Daten validieren und so sicher wie möglich sein, dass es sich um einen numerischen Javascript-Wert handelt, der in mathematischen Operationen verwendet werden kann.

jQuery und einige andere Javascript-Bibliotheken enthalten bereits eine solche Funktion, die normalerweise aufgerufen wird isNumeric. Es gibt auch einen Beitrag zum Stapelüberlauf , der allgemein als Antwort akzeptiert wurde, dieselbe allgemeine Routine, die die oben genannten Bibliotheken verwenden.

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

Erstens würde der obige Code true zurückgeben, wenn das Argument ein Array der Länge 1 wäre und dieses einzelne Element von einem Typ wäre, der von der obigen Logik als numerisch angesehen wird. Wenn es sich um ein Array handelt, ist es meiner Meinung nach nicht numerisch.

Um dieses Problem zu beheben, habe ich eine Überprüfung hinzugefügt, um Arrays von der Logik abzuziehen

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

Natürlich können Sie stattdessen auch Array.isArrayjquery $.isArrayoder prototype Object.isArrayverwendenObject.prototype.toString.call(n) !== '[object Array]'

Mein zweites Problem war, dass negative hexadezimale ganzzahlige Literalzeichenfolgen ("-0xA" -> -10) nicht als numerisch gezählt wurden. Positive hexadezimale ganzzahlige Literalzeichenfolgen ("0xA" -> 10) wurden jedoch als numerisch behandelt. Ich brauchte beide, um numerisch gültig zu sein.

Ich habe dann die Logik geändert, um dies zu berücksichtigen.

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

Wenn Sie sich Sorgen machen, dass der reguläre Ausdruck bei jedem Aufruf der Funktion erstellt wird, können Sie ihn innerhalb eines Abschlusses neu schreiben

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

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

Ich habe dann CMSs +30 Testfälle genommen und die Tests auf jsfiddle geklont und meine zusätzlichen Testfälle und meine oben beschriebene Lösung hinzugefügt.

Es ersetzt möglicherweise nicht die allgemein akzeptierte / verwendete Antwort, aber wenn dies mehr von dem ist, was Sie als Ergebnis Ihrer isNumeric-Funktion erwarten, dann wird dies hoffentlich eine Hilfe sein.

EDIT: Wie von Bergi hervorgehoben , gibt es andere mögliche Objekte, die als numerisch angesehen werden könnten, und es wäre besser, eine Whitelist als eine Blacklist zu erstellen. In diesem Sinne würde ich die Kriterien ergänzen.

Ich möchte, dass meine isNumeric-Funktion nur Zahlen oder Zeichenfolgen berücksichtigt

In diesem Sinne wäre es besser zu verwenden

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

Testen Sie die Lösungen

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
Dies ist meiner Ansicht nach die am meisten abgeschirmte Funktion; der Letzte. Die akzeptierte Antwort deckt wahrscheinlich 99,99% aller Fälle ab, aber diese hat wahrscheinlich 100% von a) Fällen mit einem geringen Overhead.
Samuel

Sie haben das Foating-Point-Literal "99.999" vergessen. Es ist eine gültige Nummer in ganz Europa außer Großbritannien
Andrii Horda

Es wurde nicht vergessen, es war nicht etwas, das ich als numerisch im Sinne von Javascript-Zahlen betrachtete, sagte das OP auchIsNumeric('99,999') => false
Xotic750

34

Ja, die integrierte isNaN(object)Analyse ist viel schneller als jede Regex-Analyse, da sie integriert und kompiliert ist, anstatt im laufenden Betrieb interpretiert zu werden.

Obwohl die Ergebnisse etwas anders sind als das, wonach Sie suchen ( probieren Sie es aus ):

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

Verwenden Sie die Funktion isNaN. Ich glaube, wenn Sie es testen !isNaN(yourstringhere), funktioniert es in jeder dieser Situationen.


Hinweis :! IsNaN (null) == true seit Number (null) == 0
Jonathan Lonowski

if (! (x == null || isNaN (x))) alert ("isNumeric"); // Aber diese Lösung akzeptiert 0x40, so dass es immer noch nicht das ist, was die Operation wollte.
einige

Beachten Sie, dass isNaN ("Infinity") === false ist, was wahrscheinlich auch nicht das ist, was Sie wollen (aber auch im wirklichen Leben nicht passieren wird).
Erik Hesselink

16

Seit jQuery 1.7 können Sie Folgendes verwenden 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

Beachten Sie nur, dass es sich im Gegensatz zu dem, was Sie gesagt haben, 0x89fum eine gültige Zahl (hexa) handelt.


Das OP möchte eine gültige Dezimalzahl , daher passt jQuery isNumeric nicht. Es schlägt auch bei sehr großen Zahlen fehl.
RobG

13

Dies kann ohne RegExp as erfolgen

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

5
Wenn wir == verwenden, wird true auch für Zahlen zurückgegeben, die als Zeichenfolgen dargestellt werden. Daher wird die "42" im Fall von "==" als gültige Zahl gezählt und im Fall von ===
Aquatic

Dies gibt true für "-0.", "-.0", ".0" und "0" zurück.
Janus Troelsen


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

hat bei mir nicht funktioniert. Als ich einen Alarm einlegte und testete, input.lengthwarundefined . Ich denke, es gibt keine Eigenschaft, um die Ganzzahllänge zu überprüfen. Also habe ich getan

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

Es hat gut funktioniert.


7

Wenn ich mich nicht irre, sollte dies mit jedem gültigen JavaScript-Zahlenwert übereinstimmen, mit Ausnahme der Konstanten ( Infinity, NaN) und der Vorzeichenoperatoren+ / -(da sie für mich nicht Teil der Zahl sind, sind sie separate Operatoren):

Ich brauchte dies für einen Tokenizer, bei dem das Senden der Nummer an JavaScript zur Auswertung keine Option war ... Es ist definitiv nicht der kürzestmögliche reguläre Ausdruck, aber ich glaube, er erfasst alle feineren Feinheiten der Zahlensyntax von 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

Gültige Zahlen wären:

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

Ungültige Zahlen wären

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

7

Das einzige Problem, das ich mit der Antwort von @ CMS hatte , ist der Ausschluss von NaNund Infinity, die für viele Situationen nützliche Zahlen sind. Eine Möglichkeit, nach NaN's zu suchen, besteht darin, nach numerischen Werten zu suchen, die nicht gleich sind NaN != NaN. Es gibt also wirklich 3 Tests, mit denen Sie sich befassen möchten ...

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

Meine isComparableNumber kommt einer anderen eleganten Antwort ziemlich nahe , verarbeitet jedoch Hex- und andere Zeichenfolgendarstellungen von Zahlen.


6

Für mich ist das der beste Weg:

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

Leider ist dies ein STRENGER numerischer Prüfer, der für alle Zeichenfolgen, die nur numerische Buchstaben enthalten, wie "0" usw.,
fehlschlägt.

6

Ich möchte Folgendes hinzufügen:

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

Positive Hex-Zahlen beginnen mit 0xund negative Hex-Zahlen beginnen mit -0x. Positive Okt-Zahlen beginnen mit 0und negative Okt-Zahlen beginnen mit -0. Dieser berücksichtigt das meiste, was bereits erwähnt wurde, enthält jedoch Hex- und Oktalzahlen, negative wissenschaftliche Zahlen, Unendlichkeit und hat dezimale wissenschaftliche Zahlen entfernt ( 4e3.2ist ungültig).

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

Ich denke, die parseFloat-Funktion kann hier die ganze Arbeit erledigen. Die folgende Funktion besteht alle Tests auf dieser Seite, einschließlich isNumeric(Infinity) == true:

function isNumeric(n) {

    return parseFloat(n) == n;
}

Ja, ich bin auch zu diesem Schluss gekommen. Mir gefällt auch die Art und Weise, wie Arrays mit dieser Methode behandelt werden. Ein Array mit einem einzelnen Wert zählt als dieser Wert, aber alles andere schlägt fehl: IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; Aber ich würde mir vorstellen, dass das Geschmackssache ist!
Mark Birbeck

4

Ein paar Tests zum Hinzufügen:

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

Ich habe mir das ausgedacht:

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

Die Lösung umfasst:

  • Ein optionales negatives Vorzeichen am Anfang
  • Eine einzelne Null oder eine oder mehrere Ziffern, die nicht mit 0 beginnen, oder nichts, solange eine Periode folgt
  • Ein Punkt, auf den eine oder mehrere Zahlen folgen

4

Ein ganzzahliger Wert kann überprüft werden durch:

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

Dieser Weg ist einfacher und schneller! Alle Tests werden überprüft!


4

Hier ist eine etwas verbesserte Version (wahrscheinlich der schnellste Weg da draußen), die ich anstelle der exakten jQuery-Variante verwende. Ich weiß wirklich nicht, warum sie diese nicht verwenden:

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

Der Nachteil von jQuerys Version ist, dass, wenn Sie eine Zeichenfolge mit führenden Zahlen und nachgestellten Buchstaben wie "123abc"dem übergeben parseFloat | parseInt, der numerische Bruch extrahiert wird und 123 zurückgegeben wird, ABER der zweite Wächter isFinitewird ihn trotzdem nicht bestehen. Mit dem unären +Operator wird es bei der allerersten Wache sterben, seit + NaN für solche Hybriden wirft :) Eine kleine Leistung, aber ich denke, ein solider semantischer Gewinn.


2
Beachten Sie, dass das unäre '+' valueOf () für ein Objekt aufruft - siehe diese jsfiddle . Dies schlägt auch für führende Leerzeichen fehl, ebenso wie die führende Antwort.
Earcam

3

Meine Lösung,

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

Es scheint in jeder Situation zu funktionieren, aber ich könnte mich irren.


Diese Regex wäre weniger verwirrend, wenn Sie Zeichen nicht unnötig entkommen, ?für {0,1}und \dfür verwenden würden [0-9]. Außerdem können Sie die (nicht) erfassenden Gruppen verwenden und vergessen , wenn Sie +sie dann einpacken . (?:){0,1}*
Alex

3

Ich verwende eine einfachere Lösung:

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

5
Dies wird bei allem mit überflüssigen Nullen am Ende fehlschlagen. Beispiel: "10.0"
Janus Troelsen

3

Das sollte funktionieren. Einige der hier bereitgestellten Funktionen sind fehlerhaft und sollten auch schneller sein als jede andere Funktion hier.

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

Erklärt:

Erstellen Sie eine Kopie von sich selbst, konvertieren Sie die Zahl in float und vergleichen Sie sich dann mit der ursprünglichen Zahl, wenn es sich noch um eine Zahl handelt (ob Ganzzahl oder float), und stimmen Sie mit der ursprünglichen Zahl überein, dh, es handelt sich tatsächlich um eine Zahl.

Es funktioniert sowohl mit numerischen Zeichenfolgen als auch mit einfachen Zahlen. Funktioniert nicht mit Hexadezimalzahlen.

Achtung: Verwendung auf eigenes Risiko, keine Garantie.


4
Verwendung auf eigenes Risiko, keine Garantie Ich würde keinen Code verwenden, bei dem der Autor nicht sicher ist;)
Alex

1
@Alex, Habe wenigstens deine eigene Meinung zu Dingen. Kritisieren Sie nicht nur die ganze Zeit.
Stewart Mbofana

3

Keine der Antworten gibt falsefür leere Zeichenfolgen zurück, ein Fix dafür ...

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

3

Um zu überprüfen, ob eine Variable eine gültige Zahl enthält und nicht nur eine Zeichenfolge, die wie eine Zahl aussieht, Number.isFinite(value) .

Dies ist Teil der Sprache seit ES2015

Beispiele:

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
Ich würde vermuten, dass viele Leute auf diese Frage verweisen, um Benutzereingaben zu analysieren, bei denen es sich normalerweise um eine Zeichenfolge handelt . Diese Antwort schlägt in diesen Fällen fehl, wie Sie in den Beispielen korrekt auflisten, z. B.Number.isFinite('0') -> false
Michael Haren

Du hast vollkommen recht. Ich habe versucht, dies klar zu machen.
Adius

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

Wenn n numerisch ist, Number(n)wird der numerische Wert zurückgegeben und toString()in eine Zeichenfolge umgewandelt. Wenn n nicht numerisch ist, Number(n)wird es zurückgegeben, NaNsodass es nicht mit dem Original übereinstimmtn


Während dieses Code-Snippet die Frage lösen kann, hilft eine Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen. Bitte versuchen Sie auch, Ihren Code nicht mit erklärenden Kommentaren zu überfüllen, da dies die Lesbarkeit sowohl des Codes als auch der Erklärungen beeinträchtigt!
Auf Wiedersehen StackExchange

2

Mir ist klar, dass dies schon oft beantwortet wurde, aber das Folgende ist ein anständiger Kandidat, der in einigen Szenarien nützlich sein kann.

Es sollte beachtet werden, dass davon ausgegangen wird, dass '.42' KEINE Zahl ist und '4.' ist KEINE Zahl, daher sollte dies berücksichtigt werden.

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

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

Der besteht isDecimalden folgenden 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');
}

Die Idee hier ist, dass jede Zahl oder Ganzzahl eine "kanonische" Zeichenfolgendarstellung hat und jede nicht-kanonische Darstellung abgelehnt werden sollte. Also setzen wir auf eine Zahl und zurück und prüfen, ob das Ergebnis die ursprüngliche Zeichenfolge ist.

Ob diese Funktionen für Sie nützlich sind, hängt vom Anwendungsfall ab. Ein Merkmal ist, dass unterschiedliche Zeichenfolgen unterschiedliche Zahlen darstellen (wenn beide den isNumber()Test bestehen).

Dies ist zB für Zahlen als Objekteigenschaftsnamen relevant.

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

2

knockoutJs Integrierte Bibliotheksvalidierungsfunktionen

Durch Erweitern wird das Feld validiert

1) Nummer

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

Testfall

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

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

Testfall

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

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

Dieses Feld akzeptiert nur Werte zwischen 5 und 10

Testfall

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

2

Wenn Sie einen speziellen Satz von Dezimalstellen validieren müssen, können Sie dieses einfache Javascript verwenden:

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

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

Nichts sehr anderes, aber wir können den Booleschen Konstruktor verwenden

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.