1826 Stimmen

Wie kann ich prüfen, ob eine Zeichenkette eine gültige Zahl ist?

Ich hoffe, dass es etwas gibt, das sich im gleichen konzeptionellen Rahmen bewegt wie das alte VB6 IsNumeric() Funktion?

32voto

Jeremy Punkte 1719

2019: Einschließlich ES3-, ES6- und TypeScript-Beispiele

Vielleicht wurde diese Frage schon zu oft aufgewärmt, aber ich habe heute auch mit dieser Frage gekämpft und wollte meine Antwort posten, da ich keine andere Antwort gesehen habe, die es so einfach oder gründlich macht:

ES3

var isNumeric = function(num){
    return (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);  
}

ES6

const isNumeric = (num) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);

Typoskript

const isNumeric = (num: any) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num as number);

Das scheint recht einfach zu sein und deckt alle Bereiche ab, die ich in den vielen anderen Beiträgen gesehen und mir selbst ausgedacht habe:

// Positive Cases
console.log(0, isNumeric(0) === true);
console.log(1, isNumeric(1) === true);
console.log(1234567890, isNumeric(1234567890) === true);
console.log('1234567890', isNumeric('1234567890') === true);
console.log('0', isNumeric('0') === true);
console.log('1', isNumeric('1') === true);
console.log('1.1', isNumeric('1.1') === true);
console.log('-1', isNumeric('-1') === true);
console.log('-1.2354', isNumeric('-1.2354') === true);
console.log('-1234567890', isNumeric('-1234567890') === true);
console.log(-1, isNumeric(-1) === true);
console.log(-32.1, isNumeric(-32.1) === true);
console.log('0x1', isNumeric('0x1') === true);  // Valid number in hex
// Negative Cases
console.log(true, isNumeric(true) === false);
console.log(false, isNumeric(false) === false);
console.log('1..1', isNumeric('1..1') === false);
console.log('1,1', isNumeric('1,1') === false);
console.log('-32.1.12', isNumeric('-32.1.12') === false);
console.log('[blank]', isNumeric('') === false);
console.log('[spaces]', isNumeric('   ') === false);
console.log('null', isNumeric(null) === false);
console.log('undefined', isNumeric(undefined) === false);
console.log([], isNumeric([]) === false);
console.log('NaN', isNumeric(NaN) === false);

Sie können auch Ihre eigenen isNumeric Funktion und fügen Sie einfach diese Anwendungsfälle ein und suchen Sie nach "true" für alle von ihnen.

Oder, um die Werte zu sehen, die jeder zurückgibt:

Results of each test against <code>isNumeric()</code>

30voto

theraccoonbear Punkte 4157

Versuchen Sie die isNan-Funktion :

Die Funktion isNaN() bestimmt, ob ein Wert eine illegale Zahl (Not-a-Number) ist.

Diese Funktion gibt true zurück, wenn der Wert gleich NaN ist. Andernfalls gibt sie false zurück.

Diese Funktion unterscheidet sich von der nummernspezifischen Zahl.isNaN() Methode.

  Die globale Funktion isNaN() wandelt den getesteten Wert in eine Zahl um und testet ihn dann.

Number.isNan() wandelt die Werte nicht in eine Zahl um und gibt für jeden Wert, der nicht vom Typ Zahl ist, nicht true zurück...

20voto

TL;DR

Es hängt weitgehend davon ab, was usted als Zahl analysiert werden soll.

Vergleich zwischen eingebauten Funktionen

Da keine der vorhandenen Quellen mich zufrieden stellte, versuchte ich herauszufinden, was mit diesen Funktionen tatsächlich geschah.

Drei unmittelbare Antworten auf diese Frage fühlten sich an wie:

  1. !isNaN(input) (was die gleiche Ausgabe ergibt wie +input === +input )
  2. !isNaN(parseFloat(input))
  3. isFinite(input)

Aber ist eine von ihnen richtig in jede Szenario?

Ich habe diese Funktionen in mehreren Fällen getestet und die Ausgabe als Markdown generiert. So sieht es aus:

input

!isNaN(input) o
+input===+input

!isNaN(
parseFloat(
input))

isFinite(
input)

Kommentar

123

-

'123'

-

12.3

-

'12.3'

-

' 12.3 '

Leere Leerzeichen werden wie erwartet abgeschnitten.

1_000_000

Numerisches Trennzeichen verstanden, auch erwartet.

'1_000_000'

Überraschung! JS parst einfach keine numerischen Trennzeichen innerhalb einer Zeichenkette. Für Details, siehe este Problem. (Warum hat dann das Parsen als Float funktioniert? Nun, das hat es nicht. )

'0b11111111'

Die binäre Form wurde verstanden, wie es sich gehört.

'0o377'

Auch Oktalform verstanden.

'0xFF'

Natürlich wird hex verstanden. Hat jemand etwas anderes gedacht?

''

Sollte die leere Zeichenfolge eine Zahl sein?

' '

Sollte eine Zeichenfolge, die nur aus Leerzeichen besteht, eine Zahl sein?

'abc'

Alle sind sich einig, dass es keine Nummer ist.

12.34Ab!@#$'

Ah! Jetzt ist es ganz verständlich, was parseFloat() tut. Das beeindruckt mich nicht, kann aber in bestimmten Fällen nützlich sein.

'10e100'

10 100 ist in der Tat eine Zahl.
Aber Vorsicht! Er ist weitaus größer als der maximale sichere Integer-Wert 2 53 (etwa 9×10 15 ). Lesen Sie este für Einzelheiten.

'10e1000'

Sagen Sie mit mir, Hilfe!
Allerdings ist das nicht so verrückt, wie es scheinen mag. In JavaScript ist ein Wert größer als ~10 308 wird auf unendlich gerundet, deshalb. Siehe aquí für Einzelheiten.
Und ja, isNaN() betrachtet die Unendlichkeit als eine Zahl, und parseFloat() analysiert Unendlichkeit als Unendlichkeit.

null

Das ist jetzt unangenehm. In JS, wenn eine Konvertierung erforderlich ist, null wird Null, und wir erhalten eine endliche Zahl.
Warum dann parseFloat(null) sollte eine NaN hier? Kann mir bitte jemand dieses Designkonzept erklären?

undefiniert

Wie erwartet.

Unendlichkeit

Wie bereits erläutert, isNaN() betrachtet die Unendlichkeit als eine Zahl, und parseFloat() analysiert Unendlichkeit als Unendlichkeit.

Welche von ihnen ist also "richtig"?

Das sollte jetzt klar sein, es hängt weitgehend davon ab, was wir brauchen . Zum Beispiel kann eine Nulleingabe als 0 betrachtet werden. In diesem Fall isFinite() wird gut funktionieren.

Auch hier werden wir vielleicht ein wenig Hilfe in Anspruch nehmen von isNaN() wenn 10 10000000000 benötigt wird, um als gültige Zahl zu gelten (obwohl die Frage bleibt, warum das so ist und wie wir damit umgehen würden)!

Natürlich können wir jedes der Szenarien manuell ausschließen.

Wie in meinem Fall brauchte ich genau die Ausgaben von isFinite() mit Ausnahme des Null-Falles, des leeren String-Falles und des Whitespace-only String-Falles. Ich hatte auch keine Kopfschmerzen wegen wirklich groß Zahlen. Mein Code sah also wie folgt aus:

/**
 * My necessity was met by the following code.
 */

if (input === null) {
    // Null input
} else if (input.trim() === '') {
    // Empty or whitespace-only string
} else if (isFinite(input)) {
    // Input is a number
} else {
    // Not a number
}

Außerdem war dies mein JavaScript, um die Tabelle zu generieren:

/**
 * Note: JavaScript does not print numeric separator inside a number.
 * In that single case, the markdown output was manually corrected.
 * Also, the comments were manually added later, of course.
 */

let inputs = [
    123, '123', 12.3, '12.3', '   12.3   ',
    1_000_000, '1_000_000',
    '0b11111111', '0o377', '0xFF',
    '', '    ',
    'abc', '12.34Ab!@#$',
    '10e100', '10e1000',
    null, undefined, Infinity];

let markdownOutput = `| \`input\` | \`!isNaN(input)\` or <br>\`+input === +input\` | \`!isNaN(parseFloat(input))\` | \`isFinite(input)\` | Comment |
| :---: | :---: | :---: | :---: | :--- |\n`;

for (let input of inputs) {
    let outputs = [];
    outputs.push(!isNaN(input));
    outputs.push(!isNaN(parseFloat(input)));
    outputs.push(isFinite(input));

    if (typeof input === 'string') {
        // Output with quotations
        console.log(`'${input}'`);
        markdownOutput += `| '${input}'`;
    } else {
        // Output without quotes
        console.log(input);
        markdownOutput += `| ${input}`;
    }

    for (let output of outputs) {
        console.log('\t' + output);
        if (output === true) {
            markdownOutput += ` | <div style="color:limegreen">true</div>`;
            // markdownOutput += ` | `; // for stackoverflow
        } else {
            markdownOutput += ` | <div style="color:orangered">false</div>`;
            // markdownOutput += ` | `; // for stackoverflow
        }
    }

    markdownOutput += ` ||\n`;
}

// Replace two or more whitespaces with $nbsp;
markdownOutput = markdownOutput.replaceAll(`  `, `&nbsp;&nbsp;`);

// Print markdown to console
console.log(markdownOutput);

18voto

mark Punkte 53152

Die Frage ist alt, aber in den gegebenen Antworten fehlen mehrere Punkte.

Wissenschaftliche Notation.

!isNaN('1e+30') es true In den meisten Fällen, in denen die Leute nach Zahlen fragen, wollen sie jedoch nicht mit Dingen wie 1e+30 .

Große Gleitkommazahlen können sich seltsam verhalten

Beobachten (mit 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
>

Andererseits:

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

Wenn man also erwartet String(Number(s)) === s dann begrenzen Sie Ihre Zeichenketten besser auf höchstens 15 Stellen (nach Weglassen führender Nullen).

Unendlichkeit

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

In Anbetracht all dessen ist zu prüfen, ob die angegebene Zeichenkette eine Zahl ist, die alle der folgenden Bedingungen erfüllt:

  • nicht wissenschaftliche Schreibweise
  • vorhersehbare Umstellung auf Number und zurück zu String
  • Endliche

ist keine so einfache Aufgabe. Hier ist eine einfache Version:

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

Aber auch diese ist bei weitem nicht vollständig. Führende Nullen werden hier nicht behandelt, aber sie versauen den Längentest.

16voto

chickens Punkte 14182

Jemand kann auch von einer Regex-basierten Antwort profitieren. Hier ist sie:

Eine Zeile isInteger:

const isInteger = num => /^-?[0-9]+$/.test(num+'');

Einzeiler istNumerisch: Akzeptiert ganze Zahlen und Dezimalzahlen

const isNumeric = num => /^-?[0-9]+(?:\.[0-9]+)?$/.test(num+'');

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X