¿Cuál es la forma más limpia y efectiva de validar los números decimales en JavaScript?
Puntos de bonificación por:
- Claridad. La solución debe ser limpia y simple.
- Multiplataforma.
Casos de prueba:
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
javascript
validation
numbers
Michael Haren
fuente
fuente
jQuery.isNumeric
función de utilidad: api.jquery.com/jQuery.isNumericjQuery.isNumeric
fallará el séptimo caso de prueba del OP (IsNumeric('0x89f') => *false*
). Sin embargo, no estoy seguro si estoy de acuerdo con este caso de prueba.Respuestas:
La respuesta de @ Joel es bastante cercana, pero fallará en los siguientes casos:
Hace algún tiempo tuve que implementar una
IsNumeric
función, para averiguar si una variable contenía un valor numérico, independientemente de su tipo , podría ser unString
valor numérico (tenía que considerar también la notación exponencial, etc.), unNumber
objeto, prácticamente cualquier cosa podría pasarse a esa función, no podría hacer ninguna suposición de tipo, cuidando la coerción de tipo (por ejemplo,+true == 1;
perotrue
no debería considerarse como"numeric"
).Creo que vale la pena compartir este conjunto de +30 pruebas unitarias realizadas en numerosas implementaciones de funciones, y también compartir el que pasa todas mis pruebas:
PS isNaN e isFinite tienen un comportamiento confuso debido a la conversión forzada a número. En ES6, Number.isNaN y Number.isFinite solucionarían estos problemas. Tenga eso en cuenta cuando los use.
Actualización : así es como jQuery lo hace ahora (2.2-estable) :
Actualización : Angular 4.3 :
fuente
2e308 > Number.MAX_VALUE
desde entonces2e308 == Infinity
. Si desea una función quetrue
también devuelva valores infinitos positivos y negativos, verifique la función No. 2 en el conjunto de pruebas . Salud.Arrrgh! No escuches las respuestas de expresiones regulares. RegEx es asqueroso por esto, y no estoy hablando solo de rendimiento. Es muy fácil hacer errores sutiles, imposibles de detectar con su expresión regular.
Si no puede usar
isNaN()
, esto debería funcionar mucho mejor:Así es como funciona:
La
(input - 0)
expresión obliga a JavaScript a hacer una 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 dará como resultadoNaN
. Este resultado numérico se compara con el valor original que ingresó. Dado que el lado izquierdo ahora es numérico, se utiliza nuevamente la coerción de tipo. Ahora que la entrada de ambos lados fue coaccionada al mismo tipo desde el mismo valor original, usted pensaría que siempre deberían ser los mismos (siempre cierto). Sin embargo, hay una regla especial que dice queNaN
nunca es igualNaN
, 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 se cae en su prueba 0x89f, pero eso es porque en muchos entornos esa es una manera 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 su razón para no usar
isNaN()
, simplemente ajuste su propia funciónisNaN()
que también puede hacer la verificación adicional.En resumen, si desea saber si un valor puede convertirse en un número, intente convertirlo en un número.
Regresé e investigué por qué una cadena de espacios en blanco no tenía el resultado esperado, y creo que ahora lo entiendo: una cadena vacía se coacciona en
0
lugar de hacerloNaN
. Simplemente recortando la cuerda antes de la verificación de longitud manejará este caso.Ejecutar las pruebas unitarias contra el nuevo código y solo falla en los literales infinito y booleano, y el único momento que debería ser un problema es si está generando código (realmente, ¿quién escribiría un literal y comprobaría si es numérico? Debes saber ), y eso sería un código extraño para generar.
Pero, de nuevo, la única razón para usar esto es si por alguna razón tienes que evitar isNaN ().
fuente
IsNumeric(' ')
,IsNumeric('\n\t')
etc. todo regresatrue
Number
literales,IsNumeric(5) == false;
verifique el conjunto de pruebas unitarias que publiqué, esta función es el número16
en el conjunto de pruebas. stackoverflow.com/questions/18082/…Esta forma parece funcionar bien:
En una linea:
Y para probarlo:
Tomé prestada esa expresión regular de http://www.codetoad.com/javascript/isnumeric.asp . Explicación:
fuente
Yahoo! UI usa esto:
fuente
new Number(1)
.Esto también funciona para números de tipo 0x23.
fuente
IsNumeric('')
,IsNumeric(' ')
,IsNumeric(true)
,IsNumeric(false)
,IsNumeric(null)
Volvertrue
en lugar defalse
.La respuesta aceptada falló su prueba # 7 y supongo que es porque cambió de opinión. Entonces esta es una respuesta a la respuesta aceptada, con la que tuve problemas.
Durante algunos proyectos, he necesitado validar algunos datos y estar lo más seguro posible de que es un valor numérico de JavaScript que se puede usar en operaciones matemáticas.
jQuery y algunas otras bibliotecas javascript ya incluyen dicha función, generalmente llamada
isNumeric
. También hay una publicación en stackoverflow que ha sido ampliamente aceptada como respuesta, la misma rutina general que utilizan las bibliotecas mencionadas anteriormente.Primero, el código anterior devolvería verdadero si el argumento era una matriz de longitud 1, y ese elemento individual era de un tipo considerado como numérico por la lógica anterior. En mi opinión, si es una matriz, entonces no es numérica.
Para aliviar este problema, agregué un cheque para descontar matrices de la lógica
Por supuesto, también puedes usar
Array.isArray
jquery$.isArray
o prototype enObject.isArray
lugar deObject.prototype.toString.call(n) !== '[object Array]'
Mi segundo problema fue que las cadenas literales enteras hexadecimales negativas ("-0xA" -> -10) no se contaban como numéricas. Sin embargo, las cadenas literales enteras hexadecimales positivas ("0xA" -> 10) se trataron como numéricas. Necesitaba que ambos fueran numéricos válidos.
Luego modifiqué la lógica para tener esto en cuenta.
Si le preocupa la creación de la expresión regular cada vez que se llama a la función, puede volver a escribirla dentro de un cierre, algo como esto
Luego tomé casos de prueba CMS +30 y cloné la prueba en jsfiddle, agregué mis casos de prueba adicionales y mi solución descrita anteriormente.
Es posible que no reemplace la respuesta ampliamente aceptada / utilizada, pero si esto es más de lo que espera como resultado de su función isNumeric, entonces espero que esto sea de alguna ayuda.
EDITAR: Como señaló Bergi , hay otros posibles objetos que podrían considerarse numéricos y sería mejor incluirlos en la lista blanca que en la lista negra. Con esto en mente, agregaría los criterios.
Quiero que mi función isNumeric considere solo números o cadenas
Con esto en mente, sería mejor usar
Prueba las soluciones
fuente
IsNumeric('99,999') => false
Sí, el incorporado
isNaN(object)
será mucho más rápido que cualquier análisis de expresiones regulares, porque está integrado y compilado, en lugar de ser interpretado sobre la marcha.Aunque los resultados son algo diferentes a lo que estás buscando ( pruébalo ):
fuente
Usa la función
isNaN
. Creo que si lo pruebas!isNaN(yourstringhere)
funciona bien para cualquiera de estas situaciones.fuente
Desde jQuery 1.7, puede usar
jQuery.isNumeric()
:Solo tenga en cuenta que, a diferencia de lo que dijo,
0x89f
es un número válido (hexa)fuente
Se puede hacer sin RegExp como
fuente
Me doy cuenta de que la pregunta original no mencionaba jQuery, pero si usa jQuery, puede hacer lo siguiente:
Simple.
https://api.jquery.com/jQuery.isNumeric/ (a partir de jQuery 1.7)
fuente
No funcionó para mí. Cuando puse una alerta y probé,
input.length
fueundefined
. Creo que no hay propiedad para verificar la longitud del entero. Entonces lo que hice fueFuncionó bien
fuente
Si no me equivoco, esto debería coincidir con cualquier valor de número de JavaScript válido, excluyendo las constantes (
Infinity
,NaN
) y los operadores de signo+
/-
(porque, en lo que a mí respecta, en realidad no son parte del número, son operadores separados):Necesitaba esto para un tokenizador, donde enviar el número a JavaScript para su evaluación no era una opción ... Definitivamente no es la expresión regular más corta posible, pero creo que atrapa todas las sutilezas más finas de la sintaxis numérica de JavaScript.
Los números válidos incluirían:
Los números inválidos serían
fuente
El único problema que tuve con la respuesta de @ CMS es la exclusión de
NaN
e Infinity, que son números útiles para muchas situaciones. Una forma de comprobar si hayNaN
's es para comprobar si hay valores numéricos que no lo hacen iguales a sí mismos,NaN != NaN
! Entonces hay realmente 3 pruebas con las que te gustaría lidiar ...My isComparableNumber está bastante cerca de otra respuesta elegante , pero maneja hexadecimales y otras representaciones de cadenas de números.
fuente
Para mí, esta es la mejor manera:
fuente
Me gustaría agregar lo siguiente:
Los números hexadecimales positivos comienzan con
0x
y los números hexadecimales negativos comienzan con-0x
. Los números de oct positivos comienzan con0
y los números de oct negativos comienzan con-0
. Este toma en consideración la mayor parte de lo que ya se ha mencionado, pero incluye números hexadecimales y octales, científico negativo, Infinito y ha eliminado el decimal científico (4e3.2
no es válido).fuente
Creo que la función parseFloat puede hacer todo el trabajo aquí. La siguiente función pasa todas las pruebas en esta página, incluyendo
isNumeric(Infinity) == true
:fuente
IsNumeric([3]) == true;
IsNumeric([]) == false;
IsNumeric([3, 4]) == false;
pero me imagino que es cuestión de gustos!Un par de pruebas para agregar:
Se me ocurrió esto:
La solución cubre:
fuente
Un valor entero puede ser verificado por:
¡De esta manera es más fácil y rápido! ¡Todas las pruebas están verificadas!
fuente
Aquí hay una versión mejorada de lil bit (probablemente la forma más rápida) que uso en lugar de la variante exacta de jQuery, realmente no sé por qué no usan esta:
La desventaja de la versión de jQuery es que si pasa una cadena con números iniciales y letras finales como
"123abc"
laparseFloat | parseInt
, extraerá la fracción numérica y devolverá 123, PERO, el segundo guardiaisFinite
fallará de todos modos. Con el+
operador unario , morirá en la primera guardia ya que + lanza NaN para tales híbridos :) Un poco de rendimiento, pero creo que es una ganancia semántica sólida.fuente
Mi solución,
Parece funcionar en todas las situaciones, pero podría estar equivocado.
fuente
?
por{0,1}
y\d
para[0-9]
. Además,+
y luego envolviéndolo(?:){0,1}
, también puede usar*
y olvidar los grupos (no) de captura.Estoy usando una solución más simple:
fuente
Esto debería funcionar. Algunas de las funciones proporcionadas aquí son defectuosas, también deberían ser más rápidas que cualquier otra función aquí.
Explicado:
Cree una copia de sí mismo, luego convierta el número en flotante, luego se compara con el número original, si todavía es un número (ya sea entero o flotante), y coincide con el número original, eso significa que, de hecho, es un número.
Funciona con cadenas numéricas y números simples. No funciona con números hexadecimales.
Advertencia: uso bajo su propio riesgo, sin garantías.
fuente
Ninguna de las respuestas regresa
false
para cadenas vacías, una solución para eso ...fuente
Para verificar si una variable contiene un número válido y no solo una Cadena que se parece a un número,
Number.isFinite(value)
se puede usar.Esto es parte del lenguaje desde ES2015
Ejemplos:
fuente
Number.isFinite('0') -> false
Si n es numérico
Number(n)
, devolverá el valor numérico y lotoString()
volverá a convertir en una cadena. Pero si n no es numéricoNumber(n)
volverá,NaN
por lo que no coincidirá con el originaln
fuente
Me doy cuenta de que esto ha sido respondido muchas veces, pero el siguiente es un candidato decente que puede ser útil en algunos escenarios.
Cabe señalar que se supone que '.42' NO es un número y '4.' NO es un número, por lo que debe tenerse en cuenta.
El
isDecimal
pasa la siguiente prueba:La idea aquí es que cada número o entero tiene una representación de cadena "canónica", y toda representación no canónica debe ser rechazada. Entonces lanzamos a un número y viceversa, y vemos si el resultado es la cadena original.
Si estas funciones son útiles para usted depende del caso de uso. Una característica es que las cadenas distintas representan números distintos (si ambas pasan la
isNumber()
prueba).Esto es relevante, por ejemplo, para números como nombres de propiedad de objeto.
fuente
funciones de validación de la biblioteca knockoutJs Inbuild
Al extenderlo, el campo se valida
1) número
self.number = ko.observable(numberValue)
.extend ({número: verdadero}) ;Caso de prueba
2) dígito
self.number = ko.observable(numberValue)
.extend ({dígito: verdadero}) ;Caso de prueba
3) min y max
self.number = ko.observable(numberValue)
.extend ({min: 5}). extend ({max: 10}) ;Este campo solo acepta valores entre 5 y 10
Caso de prueba
fuente
Si necesita validar un conjunto especial de decimales y puede usar este simple javascript:
http://codesheet.org/codesheet/x1kI7hAD
El Javascript:
fuente
isNumeric=(el)=>{return Boolean(parseFloat(el)) && isFinite(el)}
Nada muy diferente pero podemos usar el constructor booleano
fuente