Validar números decimais em JavaScript - IsNumeric ()

2376

Qual é a maneira mais limpa e eficaz de validar números decimais em JavaScript?

Pontos de bônus por:

  1. Clareza. A solução deve ser limpa e simples.
  2. Plataforma cruzada.

Casos de teste:

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
fonte
256
Apenas uma nota 99.999 é um número válido na França, é o mesmo que 99.999 no formato uk / us; portanto, se você estiver lendo uma string de um formulário de entrada, então 99.999 pode ser verdadeiro.
Re0sless
5
Confira também este post e os ótimos comentários .
powtac 23/11/2009
79
Vírgula decimal é o padrão em toda a Europa ea Rússia (exceto Reino Unido)
Calmarius
90
O jQuery 1.7 introduziu a jQuery.isNumericfunção de utilitário: api.jquery.com/jQuery.isNumeric
Ates Goral
24
jQuery.isNumericfalhará no sétimo caso de teste do OP ( IsNumeric('0x89f') => *false*). Não tenho certeza se concordo com este caso de teste, no entanto.
precisa

Respostas:

2898

A resposta de @ Joel é bem próxima, mas falhará nos seguintes 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;

Algum tempo atrás, eu tive que implementar uma IsNumericfunção, para descobrir se uma variável continha um valor numérico, independentemente de seu tipo , poderia ser uma Stringcontendo um valor numérico (eu tinha que considerar também notação exponencial etc.), um Numberobjeto, praticamente qualquer coisa poderia ser passada para essa função, eu não podia fazer nenhuma suposição de tipo, cuidando da coerção de tipo (por exemplo, +true == 1;mas truenão deveria ser considerado como "numeric").

Eu acho que vale a pena compartilhar esse conjunto de +30 testes de unidade feitos em várias implementações de funções e também compartilhar o que passa em todos os meus testes:

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

PS isNaN e isFinite têm um comportamento confuso devido à conversão forçada em número. No ES6, Number.isNaN e Number.isFinite corrigiam esses problemas. Lembre-se disso ao usá-los.


Atualização : Veja como o jQuery faz isso agora (2.2-estável) :

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

Atualização : Angular 4.3 :

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}
CMS
fonte
26
isso falha com outras localidades onde usamos vírgulas decimais, mas adicionamos `n = n.replace (/, /,". "); ' antes do retorno para corrigi-lo.
Zoltan Lengyel
5
@RobG, esse comportamento é intencional, 2e308 > Number.MAX_VALUEdesde 2e308 == Infinity. Se você deseja uma função que retorne truetambém para valores de infinito positivo e negativo, verifique a função número 2 no conjunto de testes . Felicidades.
CMS
39
A propósito, os testes de unidade agora estão sendo usados ​​pelo projeto jQuery
CMS
7
O jQuery agora também está usando esta implementação.
RichardTowers
4
A solução aqui é usar apenas o JQuery. Eles têm uma ainda melhor implementação deste agora: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli
337

Arrrgh! Não dê ouvidos às respostas da expressão regular. RegEx é nojento por isso, e não estou falando apenas de desempenho. É muito fácil cometer erros sutis, impossíveis de detectar com sua expressão regular.

Se você não pode usar isNaN(), isso deve funcionar muito melhor:

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

Veja como funciona:

A (input - 0)expressão força o JavaScript a fazer coerção de tipo no seu valor de entrada; ele deve primeiro ser interpretado como um número para a operação de subtração. Se essa conversão para um número falhar, a expressão resultará em NaN. Esse resultado numérico é então comparado ao valor original que você digitou. Como o lado esquerdo agora é numérico, a coerção de tipo é novamente usada. Agora que a entrada de ambos os lados foi coagida para o mesmo tipo a partir do mesmo valor original, você pensaria que elas sempre deveriam ser as mesmas (sempre verdadeiras). No entanto, existe uma regra especial que diz que NaNnunca é igual a NaN, portanto, um valor que não pode ser convertido em um número (e apenas valores que não podem ser convertidos em números) resultará em falso.

A verificação do comprimento é para um caso especial envolvendo seqüências de caracteres vazias. Observe também que ele cai no teste 0x89f, mas isso ocorre em muitos ambientes, que é uma boa maneira de definir um literal numérico. Se você quiser capturar esse cenário específico, poderá adicionar uma verificação adicional. Melhor ainda, se esse é o seu motivo para não usar isNaN(), basta agrupar sua própria função isNaN()que também pode fazer a verificação adicional.

Em resumo, se você quiser saber se um valor pode ser convertido em um número, tente convertê-lo em um número.


Voltei e fiz algumas pesquisas para saber por que uma string de espaço em branco não tinha a saída esperada e acho que a entendi agora: uma string vazia é coagida em 0vez de NaN. Basta aparar a corda antes que a verificação do comprimento lide com esse caso.

A execução dos testes de unidade com o novo código e ele falha apenas nos literais infinito e booleano, e o único momento que deve ser um problema é se você está gerando código (realmente, quem digitaria um literal e verificaria se é numérico? Você deve saber ), e isso seria um código estranho para gerar.

Mas, novamente, o único motivo para usar isso é se, por algum motivo, você deve evitar isNaN ().

Joel Coehoorn
fonte
28
Esta falha em cordas de espaço em branco, por exemplo IsNumeric(' '), IsNumeric('\n\t'), etc todo o retornotrue
Crescent Fresh
29
Ele também falhará nos Numberliterais; IsNumeric(5) == false;verifique o conjunto de testes de unidade que eu postei; essa função é o número 16no conjunto de testes. stackoverflow.com/questions/18082/…
CMS
20
Não acredito que ninguém apontou o uso de uma expressão regular (substituir) após avisar sobre não usar expressões regulares ... É verdade que uma substituição de espaço em branco é mais simples que uma análise de número, mas ainda é definitivamente "nojenta".
Patrick M
1
@Oriol Esse é um grande problema ... sem correções de segurança lançadas após essa data, ficar longe do XP deve ser uma prioridade.
Joel Coehoorn
1
@Oriol XP ou não, se você estiver usando o IE8 ou inferior, está usando um software desatualizado. O XP concedido não pode executar o IE9 +, portanto, use o Chrome ou o FF. As pessoas que viviam no passado usando o IE8 são a desgraça da existência de muitos desenvolvedores da web. Se eu pudesse voltar no tempo gasto, certificando-me de que um código perfeitamente bom também seja executado no IE8 ... Para mim, pegar o código que funciona no FF e no Chrome e corrigi-lo para rodar no IE8 é tão prático quanto executar um executável do Windows 8 e certificando-se de que executa o mesmo no Windows 3.1.
ChillNUT
70

Desta forma, parece funcionar bem:

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

Em uma linha:

const IsNumeric = (num) => /^-{0,1}\d*\.{0,1}\d+$/.test(num);

E para testá-lo:

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

Peguei emprestado esse regex em http://www.codetoad.com/javascript/isnumeric.asp . Explicação:

/^ 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
fonte
1
// TAMBÉM DEVE SER ADICIONADO AO SEU TESTE 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
o que isso faz? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
call-me
pode "{0,1}" ser substituído por "?", para que seu regexp fique assim: /^-?\d*\.?\d+$/?
Nuvem
agradável e simples.
the-breaker
53

Yahoo! A interface do usuário usa isso:

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}
camomileCase
fonte
25
Isso é mais verificando o tipo de variável, em oposição ao conteúdo do número. Também falhará nos números criados com new Number(1).
23411 alex
4
Como alex diz, isso realmente não responde à pergunta colocada, pois isso irá falhar se o = "1001".
Processo
50
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

Isso funciona para números do tipo 0x23 também.

user189277
fonte
29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Voltar trueem vez de false.
Oriol
49

A resposta aceita falhou no teste nº 7 e acho que é porque você mudou de idéia. Portanto, esta é uma resposta à resposta aceita, com a qual tive problemas.

Durante alguns projetos, eu precisei validar alguns dados e ter a maior certeza possível de que é um valor numérico javascript que pode ser usado em operações matemáticas.

O jQuery e algumas outras bibliotecas javascript já incluem essa função, geralmente chamada isNumeric. Há também uma postagem no stackoverflow que foi amplamente aceita como resposta, a mesma rotina geral que as bibliotecas mencionadas anteriormente estão usando.

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

Primeiro, o código acima retornaria true se o argumento fosse uma matriz de comprimento 1 e esse elemento único fosse de um tipo considerado como numérico pela lógica acima. Na minha opinião, se é uma matriz, então não é numérico.

Para aliviar esse problema, adicionei um cheque para descontar matrizes da lógica

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

Obviamente, você também pode usar Array.isArrayjquery $.isArrayou prototype em Object.isArrayvez deObject.prototype.toString.call(n) !== '[object Array]'

Meu segundo problema foi que seqüências literais inteiras hexadecimais negativas ("-0xA" -> -10) não estavam sendo contadas como numéricas. No entanto, seqüências literais inteiras hexadecimais positivas ("0xA" -> 10) foram tratadas como numéricas. Eu precisava que ambos fossem numéricos válidos.

Modifiquei a lógica para levar isso em conta.

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

Se você estiver preocupado com a criação do regex toda vez que a função for chamada, você poderá reescrevê-lo em um fechamento, algo como isto

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

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

Depois, peguei CMSs +30 casos de teste e clonei o teste no jsfiddle, adicionei meus casos de teste extras e minha solução descrita acima.

Pode não substituir a resposta amplamente aceita / usada, mas se isso é mais do que você espera como resultado de sua função isNumeric, espero que isso ajude.

Edição: Como apontado por Bergi , existem outros objetos possíveis que podem ser considerados numéricos e seria melhor colocar na lista de permissões do que na lista negra. Com isso em mente, eu acrescentaria aos critérios.

Quero que minha função isNumeric considere apenas números ou seqüências de caracteres

Com isso em mente, seria melhor 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(/^-/, ''));
}

Teste as soluções

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
fonte
2
Esta é, a meu ver, a função mais protegida; o último. A resposta aceita cobre provavelmente 99,99% de todos os casos, mas este provavelmente possui 100% de a) casos com uma pequena sobrecarga.
Samuel
Você esqueceu o literal de "99.999" Foating-Point. É um número válido em toda a Europa, exceto no Reino Unido
Andrii Horda
Ele não foi esquecido, não era algo que eu considerado um numérico no sentido de números Javascript, o OP também afirmouIsNumeric('99,999') => false
Xotic750
34

Sim, o built-in isNaN(object)será muito mais rápido do que qualquer análise de expressão regular, porque é embutido e compilado, em vez de interpretado rapidamente.

Embora os resultados sejam um pouco diferentes do que você está procurando ( experimente ):

                                              // 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
fonte
18

Use a função isNaN. Acredito que se você testar, !isNaN(yourstringhere)ele funciona bem para qualquer uma dessas situações.

bubbassauro
fonte
Nota:! IsNaN (null) == true desde Number (null) == 0
Jonathan Lonowski 15/10/2008
if (! (x == null || isNaN (x))) alert ("isNumeric"); // Mas essa solução aceita 0x40, por isso ainda não é o que o op queria.
alguns
Observe que isNaN ("Infinito") === false, o que provavelmente também não é o que você deseja (mas também não acontecerá na vida real).
Erik Hesselink
16

Desde o jQuery 1.7, você pode 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

Observe que, diferentemente do que você disse, 0x89fé um número válido (hexa)

Kuf
fonte
O OP deseja um número decimal válido , portanto, o jQuery isNumeric não é adequado. Também falha em números muito grandes.
RobG 02/11/2015
13

Isso pode ser feito sem o RegExp como

function IsNumeric(data){
    return parseFloat(data)==data;
}
Aquático
fonte
5
Se estivermos usando ==, ele retornará verdadeiro mesmo para números apresentados como seqüências de caracteres. Assim, o "42" será contado como número válido em caso de "==" e será contado como inválida em caso de ===
Aquatic
isso retorna verdadeiro em "-0.", "-.0", ".0" e "0".
Janus Troelsen
8
return (input - 0) == input && input.length > 0;

não funcionou para mim. Quando coloquei em alerta e testei, input.lengthfoi undefined. Eu acho que não há propriedade para verificar o comprimento inteiro. Então o que eu fiz foi

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

Funcionou bem.

jayakumar
fonte
7

Se não me engano, isso deve corresponder a qualquer valor válido de número JavaScript, excluindo constantes ( Infinity, NaN) e os operadores de sinal +/ -(porque na verdade não fazem parte do número, no que me diz respeito, são operadores separados):

Eu precisava disso para um tokenizador, onde enviar o número para JavaScript para avaliação não era uma opção ... Definitivamente, não é a expressão regular mais curta possível, mas acredito que ele captura todas as sutilezas mais delicadas da sintaxe de número do 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

Os números válidos incluem:

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

Números inválidos seriam

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

O único problema que tive com a resposta do @ CMS é a exclusão de NaNe Infinity, que são números úteis para muitas situações. Uma maneira de verificar se há NaNvalores numéricos que não se igualam a eles NaN != NaN! Então, existem realmente três testes com os quais você gostaria de lidar ...

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

Meu isComparableNumber está bem próximo de outra resposta elegante , mas lida com representações hexadecimais e outras strings de números.

hobs
fonte
6

Para mim, esta é a melhor maneira:

isNumber : function(v){
   return typeof v === 'number' && isFinite(v);
}
InsertNameHere
fonte
Infelizmente, esta é verificador numérico meio rigorosa que irá falhar por qualquer string contendo apenas letras numéricos, como "0" etc ...
Arman McHitarian
6

Eu gostaria de adicionar o seguinte:

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

Os números hexadecimais positivos começam com 0xe os números hexadecimais negativos começam com -0x. Os números de outubro positivos começam com 0e os números de outubro negativos começam com -0. Este leva a maior parte do que já foi mencionado em consideração, mas inclui números hexadecimais e octais, negativo científico, Infinito e removeu decimal científico ( 4e3.2não é 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
fonte
6

Eu acho que a função parseFloat pode fazer todo o trabalho aqui. A função abaixo passa em todos os testes desta página, incluindo isNumeric(Infinity) == true:

function isNumeric(n) {

    return parseFloat(n) == n;
}
John Mikic
fonte
Sim, eu também cheguei a essa conclusão. Também gosto bastante da maneira como as matrizes são tratadas usando esse método; uma matriz com um único valor conta como esse valor, mas tudo o resto falha: IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; mas imagino que seja uma questão de gosto!
precisa saber é o seguinte
4

Alguns testes a serem adicionados:

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

Eu vim com isso:

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

A solução abrange:

  • Um sinal negativo opcional no início
  • Um único zero, ou um ou mais dígitos que não começam com 0, ou nada, desde que um período siga
  • Um período seguido por 1 ou mais números
pottedmeat
fonte
4

Um valor inteiro pode ser verificado por:

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

Desta forma, é mais fácil e rápido! Todos os testes são verificados!

solidarius
fonte
4

Aqui está uma pequena versão melhorada (provavelmente a maneira mais rápida), que eu uso em vez da variante exata do jQuery, eu realmente não sei por que eles não usam esta:

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

A desvantagem da versão do jQuery é que, se você passar uma string com números iniciais e letras finais, como "123abc"o parseFloat | parseIntextrairá a fração numérica e retornará 123, MAS, o segundo guarda isFinitefalhará de qualquer maneira. Com o +operador unário , ele morrerá na primeira guarda, já que o + lança NaN para esses híbridos :) Um pouco de desempenho ainda acho que um sólido ganho semântico.

Arman McHitarian
fonte
2
Cuidado, o '+' unário invocará valueOf () em um objeto - veja este jsfiddle . Além disso, isso também falha no espaço em branco à esquerda, assim como a resposta à frente.
earcam 24/09/13
3

Minha solução

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 em todas as situações, mas posso estar errado.

Manusoftar
fonte
Esse regex seria menos confuso se você não escapasse desnecessariamente dos caracteres, use ?para {0,1}e \dpara [0-9]. Além disso, +e depois envolvê-lo (?:){0,1}, você também pode usar *e esquecer os grupos (não) de captura.
alex
3

Estou usando uma solução mais simples:

function isNumber(num) {
    return parseFloat(num).toString() == num
}
Ali Gonabadi
fonte
5
isso falhará em qualquer coisa com 0 supérfluo no final. exemplo: "10.0"
Janus Troelsen
3

Isso deve funcionar. Algumas das funções fornecidas aqui são falhas, também devem ser mais rápidas do que qualquer outra função aqui.

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

Explicado:

Crie uma cópia de si mesmo, depois converta o número em float e, em seguida, compare-se com o número original, se ainda for um número (inteiro ou flutuante) e corresponda ao número original, ou seja, é realmente um número.

Funciona com seqüências numéricas e números simples. Não funciona com números hexadecimais.

Aviso: use por sua conta e risco, sem garantias.

user532188
fonte
4
use a seu próprio risco, sem garantias Eu não usaria um código que o autor não está confiante sobre;)
alex
1
@ Alex, pelo menos tenha sua própria opinião sobre as coisas. Não basta criticar o tempo todo.
Stewart Mbofana
3

Nenhuma das respostas retorna falsepara cadeias vazias, uma correção para isso ...

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

Para verificar se uma variável contém um número válido e não apenas uma String que se parece com um número, Number.isFinite(value)pode ser usada.

Isso faz parte do idioma desde o ES2015

Exemplos:

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
fonte
1
Eu acho que muitas pessoas se referem a esta pergunta para analisar a entrada do usuário, que normalmente será uma string . Essa resposta falha nesses casos, como você listou corretamente nos exemplos, por exemploNumber.isFinite('0') -> false
Michael Haren
Você está completamente certo. Eu tentei deixar isso bem claro.
Adius 12/04
3
function inNumeric(n){
   return Number(n).toString() === n;
}

Se n for numérico Number(n), retornará o valor numérico e toString()retornará para uma sequência. Mas se n não for numérico Number(n), retornará NaNpara que não corresponda ao originaln

chrmcpn
fonte
Embora esse trecho de código possa resolver a questão, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código. Tente também não sobrecarregar seu código com comentários explicativos, pois isso reduz a legibilidade do código e das explicações!
Adeus StackExchange
2

Sei que isso já foi respondido muitas vezes, mas a seguir é um candidato decente que pode ser útil em alguns cenários.

Note-se que assume que '.42' NÃO é um número e '4'. NÃO é um número, portanto, isso deve ser levado em consideração.

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

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

O isDecimalpassa no seguinte teste:

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

A idéia aqui é que todo número ou número inteiro tenha uma representação de string "canônica" e toda representação não-canônica deve ser rejeitada. Então, convertemos para um número e retornamos e vemos se o resultado é a sequência original.

Se essas funções são úteis para você depende do caso de uso. Uma característica é que cadeias distintas representam números distintos (se ambas passarem no isNumber()teste).

Isso é relevante, por exemplo, para números como nomes de propriedades de objetos.

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

funções de validação da biblioteca Inbuild do knockoutJs

Estendendo-o, o campo é validado

1) número

self.number = ko.observable(numberValue).extend ({number: true}) ;

Caso de teste

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

Caso de teste

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

self.number = ko.observable(numberValue).extend ({min: 5}). extend ({max: 10}) ;

Este campo aceita valores entre 5 e 10 apenas

Caso de teste

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

Se você precisar validar um conjunto especial de decimais y, poderá usar este javascript simples:

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

O 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
fonte
2

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

Nada muito diferente, mas podemos usar o construtor booleano

Shishir Arora
fonte