Solución:
La respuesta de @ Joel es bastante cercana, pero fallará en los siguientes casos:
// Whitespace strings:
IsNumeric(' ') == true;
IsNumeric('tt') == true;
IsNumeric('nr') == true;
// Number literals:
IsNumeric(-1) == false;
IsNumeric(0) == false;
IsNumeric(1.1) == false;
IsNumeric(8e5) == false;
Hace algún tiempo tuve que implementar un IsNumeric
función, para averiguar si una variable contiene un valor numérico, independientemente de su tipo, podría ser un String
que contiene un valor numérico (tuve que considerar también la notación exponencial, etc.), un Number
objeto, virtualmente cualquier cosa podría pasarse a esa función, no pude hacer suposiciones de tipo, ocupándome de la coerción de tipos (por ejemplo. +true == 1;
pero true
no debe considerarse como "numeric"
).
Creo que vale la pena compartir este conjunto de +30 pruebas unitarias hecho a numerosas implementaciones de funciones, y también comparto la que pasa todas mis pruebas:
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
PD isNaN & isFinite tienen un comportamiento confuso debido a la conversión forzada a un número. En ES6, Number.isNaN y Number.isFinite solucionarían estos problemas. Tenga eso en cuenta al usarlos.
Actualizar : Así es como lo hace jQuery ahora (2.2-estable):
isNumeric: function(obj) {
var realStringObj = obj && obj.toString();
return !jQuery.isArray(obj) && (realStringObj - parseFloat(realStringObj) + 1) >= 0;
}
Actualizar : Angular 4.3:
export function isNumeric(value: any): boolean {
return !isNaN(value - parseFloat(value));
}
Arrrgh! No escuches las respuestas de expresiones regulares. La expresión regular es asquerosa para esto, y no me refiero solo al rendimiento. Es tan fácil cometer errores sutiles que es imposible detectar errores con tu expresión regular.
Si no puedes usar isNaN()
, esto debería funcionar mucho mejor:
function IsNumeric(input)
{
return (input - 0) == input && (''+input).trim().length > 0;
}
Así es como funciona:
los (input - 0)
expresión obliga a JavaScript a hacer coerción de tipo en su valor de entrada; primero debe interpretarse como un número para la operación de resta. Si esa conversión a un número falla, la expresión resultará en NaN
. Esta numérico El resultado luego se compara con el valor original que ingresó. Dado que el lado izquierdo ahora es numérico, se usa nuevamente la coerción de tipo. Ahora que la entrada de ambos lados fue coaccionada al mismo tipo desde el mismo valor original, pensaría que siempre deberían ser iguales (siempre cierto). Sin embargo, hay una regla especial que dice NaN
nunca es igual a NaN
, por lo que un valor que no se puede convertir en un número (y solo los valores que no se pueden convertir en números) resultará en falso.
La verificación de la longitud es para un caso especial que involucra cadenas vacías. También tenga en cuenta que cae en su prueba 0x89f, pero eso se debe a que en muchos entornos esa es una forma correcta de definir un número literal. Si desea captar ese escenario específico, puede agregar una verificación adicional. Aún mejor, si esa es tu razón para no usar isNaN()
luego simplemente envuelve tu propia función isNaN()
que también puede hacer la verificación adicional.
En resumen, Si desea saber si un valor se puede convertir en un número, intente convertirlo en un número.
Regresé e investigué un poco para por qué una cadena de espacios en blanco no tenía la salida esperada, y creo que la entiendo ahora: una cadena vacía es forzada a 0
en vez de NaN
. Simplemente recortando la cuerda antes de la verificación de longitud se encargará de este caso.
Ejecutar las pruebas unitarias contra el nuevo código y solo falla en los literales infinito y booleano, y la única vez que debería ser un problema es si está generando código (en realidad, ¿quién escribiría un literal y verificaría si es numérico? Debería saber), y ese sería un código extraño de generar.
Pero otra vez, la única razón para usar esto es si por alguna razón tienes que evitar isNaN ().
De esta manera parece funcionar bien:
function IsNumeric(input){
var RE = /^-{0,1}d*.{0,1}d+$/;
return (RE.test(input));
}
En una línea:
const IsNumeric = (num) => /^-{0,1}d*.{0,1}d+$/.test(num);
Y para probarlo:
const IsNumeric = (num) => /^-{0,1}d*.{0,1}d+$/.test(num);
function TestIsNumeric(){
var results=""
results += (IsNumeric('-1')?"Pass":"Fail") + ": IsNumeric('-1') => truen";
results += (IsNumeric('-1.5')?"Pass":"Fail") + ": IsNumeric('-1.5') => truen";
results += (IsNumeric('0')?"Pass":"Fail") + ": IsNumeric('0') => truen";
results += (IsNumeric('0.42')?"Pass":"Fail") + ": IsNumeric('0.42') => truen";
results += (IsNumeric('.42')?"Pass":"Fail") + ": IsNumeric('.42') => truen";
results += (!IsNumeric('99,999')?"Pass":"Fail") + ": IsNumeric('99,999') => falsen";
results += (!IsNumeric('0x89f')?"Pass":"Fail") + ": IsNumeric('0x89f') => falsen";
results += (!IsNumeric('#abcdef')?"Pass":"Fail") + ": IsNumeric('#abcdef') => falsen";
results += (!IsNumeric('1.2.3')?"Pass":"Fail") + ": IsNumeric('1.2.3') => falsen";
results += (!IsNumeric('')?"Pass":"Fail") + ": IsNumeric('') => falsen";
results += (!IsNumeric('blah')?"Pass":"Fail") + ": IsNumeric('blah') => falsen";
return results;
}
console.log(TestIsNumeric());
.as-console-wrapper { max-height: 100% !important; top: 0; }
Tomé prestada esa expresión regular de http://www.codetoad.com/javascript/isnumeric.asp. Explicación:
/^ 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