Ich hoffe, dass es etwas gibt, das sich im gleichen konzeptionellen Rahmen bewegt wie das alte VB6 IsNumeric()
Funktion?
Antworten
Zu viele Anzeigen?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:
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...
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:
!isNaN(input)
(was die gleiche Ausgabe ergibt wie+input === +input
)!isNaN(parseFloat(input))
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(` `, ` `);
// Print markdown to console
console.log(markdownOutput);
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 zuString
- 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.