Validar números decimales en JavaScript - IsNumeric ()

2377

¿Cuál es la forma más limpia y efectiva de validar los números decimales en JavaScript?

Puntos de bonificación por:

  1. Claridad. La solución debe ser limpia y simple.
  2. 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
Michael Haren
fuente
256
Solo una nota 99.999 es un número válido en Francia, es lo mismo que 99.999 en formato uk / us, por lo que si está leyendo en una cadena de, digamos, un formulario de entrada, entonces 99.999 puede ser cierto.
Re0sless
79
La coma decimal es el estándar en toda Europa y Rusia (excepto Reino Unido)
Calmarius
90
jQuery 1.7 ha introducido la jQuery.isNumericfunción de utilidad: api.jquery.com/jQuery.isNumeric
Ates Goral
24
jQuery.isNumericfallará 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.
Tim Lehner

Respuestas:

2898

La respuesta de @ Joel es bastante cercana, pero fallará en los siguientes casos:

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

Hace algún tiempo tuve que implementar una IsNumericfunción, para averiguar si una variable contenía un valor numérico, independientemente de su tipo , podría ser un Stringvalor numérico (tenía que considerar también la notación exponencial, etc.), un Numberobjeto, 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;pero trueno 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:

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

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

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

Actualización : Angular 4.3 :

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}
CMS
fuente
26
esto falla con otras configuraciones regionales donde usamos comas decimales, pero agregamos `n = n.replace (/, /,". "); ' antes del regreso para arreglarlo.
Zoltan Lengyel
55
@RobG, ese comportamiento es intencional 2e308 > Number.MAX_VALUEdesde entonces 2e308 == Infinity. Si desea una función que truetambién devuelva valores infinitos positivos y negativos, verifique la función No. 2 en el conjunto de pruebas . Salud.
CMS
39
Por cierto, las pruebas unitarias ahora están siendo utilizadas por el proyecto jQuery
CMS
77
jQuery ahora también está utilizando esta implementación.
RichardTowers
44
La solución aquí es usar JQuery. Ahora tienen una implementación aún mejor de esto: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli
337

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:

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

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 resultado NaN. 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 que NaNnunca es igual 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 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ón isNaN()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 0lugar de hacerlo NaN. 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 ().

Joel Coehoorn
fuente
28
Esto falla en las cadenas de espacios en blanco, por ejemplo IsNumeric(' '), IsNumeric('\n\t')etc. todo regresatrue
Crescent Fresh
29
También fallará en los Numberliterales, IsNumeric(5) == false;verifique el conjunto de pruebas unitarias que publiqué, esta función es el número 16en el conjunto de pruebas. stackoverflow.com/questions/18082/…
CMS
20
No puedo creer que nadie haya señalado el uso de una expresión regular (reemplazar) después de advertir sobre no usar expresiones regulares ... Por supuesto, un reemplazo de espacios en blanco es más simple que un análisis numérico, pero definitivamente es "repulsivo".
Patrick M
1
@Oriol Ese es un gran problema ... sin revisiones de seguridad lanzadas después de esa fecha, alejarse de XP debería ser una prioridad.
Joel Coehoorn
1
@Oriol XP o no, si está utilizando IE8 o inferior, está utilizando un software terriblemente desactualizado. Granted XP no puede ejecutar IE9 +, así que usa Chrome o FF. Las personas que vivieron en el pasado usando IE8 son la ruina de la existencia de muchos desarrolladores web. Si pudiera recuperar el tiempo que he pasado asegurándome de que un código perfectamente bueno también se ejecute en IE8 ... Para mí, tomar el código que funciona en FF y Chrome y parchearlo para que se ejecute en IE8 es casi tan práctico como tomar un ejecutable de Windows 8 y asegurándose de que funciona igual en Windows 3.1.
chiliNUT
70

Esta forma parece funcionar bien:

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

En una linea:

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

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
Michael Haren
fuente
1
// TAMBIÉN DEBE AGREGARSE A SU PRUEBA resultados + = (! IsNumeric ('-')? "Pass": "Fail") + ": IsNumeric ('-') => false \ n"; resultados + = (! IsNumeric ('01 ')? "Pass": "Fail") + ": IsNumeric ('01') => false \ n"; resultados + = (! IsNumeric ('- 01')? "Pass": "Fail") + ": IsNumeric ('- 01') => false \ n"; resultados + = (! IsNumeric ('000')? "Pass": "Fail") + ": IsNumeric ('000') => false \ n";
Dan
¿Qué hace esto? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
llámame el
¿se puede reemplazar "{0,1}" con "?", de modo que su expresión regular se verá así: /^-?\d*\.?\d+$/?
Nube
Agradable y simple.
El rompedor
53

Yahoo! UI usa esto:

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}
camomila
fuente
25
Eso es más verificar el tipo de variable en lugar de los contenidos del número. También fallará en los números creados con new Number(1).
alex
44
Como dice alex, esto en realidad no responde a la pregunta planteada ya que fallará si o = "1001".
Caso del
50
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

Esto también funciona para números de tipo 0x23.

usuario189277
fuente
29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Volver trueen lugar de false.
Oriol
49

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.

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

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

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

Por supuesto, también puedes usar Array.isArrayjquery $.isArrayo prototype en Object.isArraylugar 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.

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

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

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

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

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

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

Prueba las soluciones

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>

Xotic750
fuente
2
En mi opinión, esta es la función más protegida; el último. La respuesta aceptada cubre probablemente el 99.99% de todos los casos, pero este tiene probablemente el 100% de a) casos con una pequeña sobrecarga.
Samuel
Se olvidó del literal "99,999" Foating-Point. Es un número válido en toda Europa, excepto Reino Unido
Andrii Horda
No se olvidó, no era algo que yo considerara numérico en el sentido de los números Javascript, el OP también declaróIsNumeric('99,999') => false
Xotic750
34

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

                                              // 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
travis
fuente
18

Usa la función isNaN. Creo que si lo pruebas !isNaN(yourstringhere)funciona bien para cualquiera de estas situaciones.

bubbassauro
fuente
Nota:! IsNaN (nulo) == verdadero ya que Número (nulo) == 0
Jonathan Lonowski
if (! (x == null || isNaN (x))) alert ("isNumeric"); // Pero esta solución acepta 0x40, por lo que todavía no es lo que el operador quería.
poco
Tenga en cuenta que isNaN ("Infinity") === false, que probablemente tampoco sea lo que desea (pero tampoco sucederá en la vida real).
Erik Hesselink
16

Desde jQuery 1.7, puede usar 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

Solo tenga en cuenta que, a diferencia de lo que dijo, 0x89fes un número válido (hexa)

Kuf
fuente
El OP quiere un número decimal válido , por lo que jQuery isNumeric no es adecuado. También falla para números muy grandes.
RobG
13

Se puede hacer sin RegExp como

function IsNumeric(data){
    return parseFloat(data)==data;
}
Acuático
fuente
55
Si estamos utilizando ==, devolverá verdadero incluso para los números presentados como cadenas. Por lo tanto, el "42" se contará como un número válido en el caso de "==" y se contará como no válido en el caso de ===
Aquatic
esto devuelve verdadero en "-0.", "-.0", ".0" y "0".
Janus Troelsen
8
return (input - 0) == input && input.length > 0;

No funcionó para mí. Cuando puse una alerta y probé, input.lengthfue undefined. Creo que no hay propiedad para verificar la longitud del entero. Entonces lo que hice fue

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

Funcionó bien

jayakumar
fuente
7

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.

/^(?:(?:(?:[1-9]\d*|\d)\.\d*|(?:[1-9]\d*|\d)?\.\d+|(?:[1-9]\d*|\d)) 
(?:[e]\d+)?|0[0-7]+|0x[0-9a-f]+)$/i

Los números válidos incluirían:

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

Los números inválidos serían

 - 00e1
 - 01e1
 - 00.0
 - 00x0
 - .
 - .e0
Jonathan Spooner
fuente
7

El único problema que tuve con la respuesta de @ CMS es la exclusión de NaNe Infinity, que son números útiles para muchas situaciones. Una forma de comprobar si hay NaN'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 ...

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

My isComparableNumber está bastante cerca de otra respuesta elegante , pero maneja hexadecimales y otras representaciones de cadenas de números.

placas
fuente
6

Para mí, esta es la mejor manera:

isNumber : function(v){
   return typeof v === 'number' && isFinite(v);
}
InsertarNombreAquí
fuente
Desafortunadamente, este es un verificador numérico un poco ESTRICTO que fallará para cualquier cadena que contenga solo letras numéricas, como "0", etc ...
Arman McHitarian
6

Me gustaría agregar lo siguiente:

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

Los números hexadecimales positivos comienzan con 0xy los números hexadecimales negativos comienzan con -0x. Los números de oct positivos comienzan con 0y 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.2no es válido).

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));
}
Marius
fuente
6

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:

function isNumeric(n) {

    return parseFloat(n) == n;
}
John Mikic
fuente
Sí, también llegué a esta conclusión. También me gusta bastante la forma en que se tratan las matrices usando este método; una matriz con un solo valor cuenta como ese valor, pero todo lo demás falla: ¡ IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; pero me imagino que es cuestión de gustos!
Mark Birbeck el
4

Un par de pruebas para agregar:

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

Se me ocurrió esto:

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

La solución cubre:

  • Un signo negativo opcional al principio
  • Un solo cero, o uno o más dígitos que no comienzan con 0, o nada, siempre que siga un período
  • Un período seguido de 1 o más números.
carne en maceta
fuente
4

Un valor entero puede ser verificado por:

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

¡De esta manera es más fácil y rápido! ¡Todas las pruebas están verificadas!

solidarius
fuente
4

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:

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

La desventaja de la versión de jQuery es que si pasa una cadena con números iniciales y letras finales como "123abc"la parseFloat | parseInt, extraerá la fracción numérica y devolverá 123, PERO, el segundo guardia isFinitefallará 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.

Arman McHitarian
fuente
2
Tenga en cuenta que el '+' unario invocará valueOf () en un objeto; consulte este jsfiddle . Además, esto también falla para los espacios en blanco iniciales, al igual que la respuesta principal.
Earcam
3

Mi solución,

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

Parece funcionar en todas las situaciones, pero podría estar equivocado.

Manusoftar
fuente
Esa expresión regular sería menos confusa si no escaparas innecesariamente de los personajes, usa ?por {0,1}y \dpara [0-9]. Además, +y luego envolviéndolo (?:){0,1}, también puede usar *y olvidar los grupos (no) de captura.
alex
3

Estoy usando una solución más simple:

function isNumber(num) {
    return parseFloat(num).toString() == num
}
Ali Gonabadi
fuente
55
esto fallará en cualquier cosa con 0 superfluos al final. ejemplo: "10.0"
Janus Troelsen
3

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

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

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.

usuario532188
fuente
44
use bajo su propio riesgo, no hay garantías de que no usaría código sobre el que el autor no confía;)
alex
1
@Alex, al menos ten tu propia opinión sobre las cosas. No solo critiques todo el tiempo.
Stewart Mbofana
3

Ninguna de las respuestas regresa falsepara cadenas vacías, una solución para eso ...

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

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:

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
adius
fuente
1
Supongo que muchas personas se refieren a esta pregunta para analizar la entrada del usuario, que generalmente será una cadena . Esta respuesta falla en esos casos, como se enumera correctamente en los ejemplos, por ejemploNumber.isFinite('0') -> false
Michael Haren
Tienes toda la razón. Traté de aclarar esto al frente.
adius
3
function inNumeric(n){
   return Number(n).toString() === n;
}

Si n es numérico Number(n), devolverá el valor numérico y lo toString()volverá a convertir en una cadena. Pero si n no es numérico Number(n)volverá, NaNpor lo que no coincidirá con el originaln

revs chrmcpn
fuente
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código. ¡Intente también no saturar su código con comentarios explicativos, ya que esto reduce la legibilidad tanto del código como de las explicaciones!
Adiós StackExchange
2

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.

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

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

El isDecimalpasa la siguiente prueba:

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

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.

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

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

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) dígito

self.number = ko.observable(numberValue).extend ({dígito: verdadero}) ;

Caso de prueba

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

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

Si necesita validar un conjunto especial de decimales y puede usar este simple javascript:

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

El 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;
}
studio-klik
fuente
2

isNumeric=(el)=>{return Boolean(parseFloat(el)) && isFinite(el)}

Nada muy diferente pero podemos usar el constructor booleano

Shishir Arora
fuente