Pergunta

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

Pontos de bônus para:

  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
Foi útil?

Solução

Resposta do @Joel está bem próximo, 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;

Há algum tempo tive que implementar um IsNumeric função, para descobrir se uma variável continha um valor numérico, independentemente do seu tipo, poderia ser um String contendo um valor numérico (tive que considerar também a notação exponencial, etc.), um Number objeto, praticamente qualquer coisa poderia ser passada para essa função, eu não poderia fazer nenhuma suposição de tipo, cuidando da coerção de tipo (por exemplo. +true == 1; mas true não deveria ser considerado como "numeric").

Acho que vale a pena compartilhar esse conjunto de +30 testes unitários feito em inúmeras implementações de funções e também compartilho aquela que passa em todos os meus testes:

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

P.S. éNaN & éFinito tem um comportamento confuso devido à conversão forçada para número.No ES6, Número.isNaN & Número.isFinite resolveria esses problemas.Tenha isso em mente ao usá-los.


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

Atualizar : Angular 4.3:

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}

Outras dicas

Arrgh!Não dê ouvidos às respostas das expressões regulares.RegEx é nojento para isso, e não estou falando apenas de desempenho.É tão fácil ser sutil que é impossível detectar erros em 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:

O (input - 0) expressão força o JavaScript a fazer coerção de tipo em seu valor de entrada;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 numérico o resultado é então comparado com o valor original que você passou.Como o lado esquerdo agora é numérico, o tipo coerção é usado novamente.Agora que a entrada de ambos os lados foi forçada para o mesmo tipo a partir do mesmo valor original, você pensaria que eles deveriam ser sempre os mesmos (sempre verdadeiros).No entanto, há uma regra especial que diz NaN nunca é igual a NaN, e, portanto, um valor que não pode ser convertido em 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 que envolve strings vazias.Observe também que ele falha no teste 0x89f, mas isso ocorre porque em muitos ambientes essa é uma boa maneira de definir um número literal.Se você quiser capturar esse cenário específico, poderá adicionar uma verificação adicional.Melhor ainda, se esse for o seu motivo para não usar isNaN() então basta envolver sua própria função isNaN() isso também pode fazer a verificação adicional.

Resumindo, 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 por que uma string de espaço em branco não teve a saída esperada e acho que entendi agora:uma string vazia é forçada a 0 em vez de NaN.Simplesmente aparar a corda antes da verificação do comprimento resolverá esse caso.

Executando os testes de unidade no novo código e ele falha apenas nos literais infinito e booleano, e a única vez que isso deve ser um problema é se você estiver gerando código (na verdade, quem digitaria um literal e verificaria se é numérico?Você deve saber), e isso seria um código estranho para gerar.

Mas novamente, a única razão para usar isso é se por algum motivo você precisar evitar isNaN().

Desta forma parece funcionar bem:

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

E para testar:

// alert(TestIsNumeric());

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

Peguei emprestado esse regex de 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

Yahoo!IU usa isso:

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

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

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

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

jQuery e algumas outras bibliotecas javascript já incluem essa função, geralmente chamada isNumeric.Há também um postar no stackoverflow isso foi amplamente aceito como resposta, a mesma rotina geral que as bibliotecas mencionadas acima estão usando.

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

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

Para aliviar esse problema, adicionei uma verificação para descontar arrays da lógica

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

Claro, você também pode usar Array.isArray, jquery $.isArray ou protótipo Object.isArray em vez de Object.prototype.toString.call(n) !== '[object Array]'

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

Em seguida, modifiquei a lógica para levar isso em consideração.

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

Se você está preocupado com a criação da regex cada vez que a função é chamada, você pode reescrevê-la dentro de um encerramento, 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, ''));
  };
}());

Então peguei CMSs +30 casos de teste e clonou o testando 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 for mais do que você espera como resultado de sua função isNumeric, espero que isso seja de alguma ajuda.

EDITAR: Como apontado por Bergi, existem outros objetos possíveis que podem ser considerados numéricos e seria melhor colocá-los na lista branca 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 strings

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>

Sim, o embutido isNaN(object) será muito mais rápido do que qualquer análise de regex, porque é integrado e compilado, em vez de interpretado em tempo real.

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

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

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

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

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

Isso pode ser feito sem RegExp como

function IsNumeric(data){
    return parseFloat(data)==data;
}

Sei que a pergunta original não mencionou jQuery, mas se você usar jQuery, poderá fazer:

$.isNumeric(val)

Simples.

https://api.jquery.com/jQuery.isNumeric/ (a partir do jQuery 1.7)

Se não me engano, isso deve corresponder a qualquer valor numérico JavaScript válido, 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 tokenizer, 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 ela captura todas as sutilezas da sintaxe numérica 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 incluiriam:

 - 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
return (input - 0) == input && input.length > 0;

não funcionou para mim.Quando coloquei um alerta e testei, input.length era undefined.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.

Para mim, esta é a melhor maneira:

isNumber : function(v){
   return typeof v === 'number' && isFinite(v);
}

Único problema que tive com @CMS responder é a exclusão de NaN e Infinito, que são números úteis para muitas situações.Uma maneira de verificar NaNé verificar se há valores numéricos que não são iguais, NaN != NaN!Portanto, 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 é bem próximo de outro elegante responder, mas lida com representações hexadecimais e outras representações de números.

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

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

Aqui está uma versão um pouco melhorada (provavelmente a maneira mais rápida que existe) 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 | parseInt extrairá a fração numérica e retornará 123, MAS, o segundo guarda isFinite irá falhar de qualquer maneira.Com o unário + Operador Ele morrerá no primeiro guarda, já que + lança Nan para tais híbridos :) Um pouco de desempenho, mas acho que um sólido ganho semântico.

Eu gostaria de adicionar o seguinte:

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

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

Alguns testes para adicionar:

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

Eu descobri 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 comecem com 0, ou nada, desde que haja um ponto final
  • Um ponto final seguido por 1 ou mais números

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.

Isso deve funcionar.Algumas das funções fornecidas aqui são falhas e também deveriam 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, converta o número em float e compare-se com o número original, se ainda for um número (seja inteiro ou float) e corresponda ao número original, ou seja, é de fato um número.

Funciona com strings numéricas e também com números simples.Não funciona com números hexadecimais.

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

Nenhuma das respostas retorna false para strings vazias, uma correção para isso ...

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

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

Isso faz parte da linguagem desdeES2015

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

Estou usando uma solução mais simples:

function isNumber(num) {
    return parseFloat(num).toString() == num
}

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

Deve -se notar que assume que '.42' não é um número e '4.' ' não é um número, então isso deve ser levado em consideração.

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

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

O isDecimal passa 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 ideia 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 voltamos e vemos se o resultado é a string original.

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

Isto é relevante, por ex.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.

Funções de validação da biblioteca knockoutJs Inbuild

Ao estendê-lo, o campo é validado

1) número

self.number = ko.observable(numberValue).extend({ número:verdadeiro});

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) mínimo e máximo

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

Este campo aceita apenas valores entre 5 e 10

Caso de teste

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

Você pode minimizar essa função de várias maneiras e também implementá-la com um regex personalizado para valores negativos ou gráficos personalizados:

$('.number').on('input',function(){
    var n=$(this).val().replace(/ /g,'').replace(/\D/g,'');
    if (!$.isNumeric(n))
        $(this).val(n.slice(0, -1))
    else
        $(this).val(n)
});
function inNumeric(n){
   return Number(n).toString() === n;
}

Se n for numérico Number(n) retornará o valor numérico e toString() irá transformá-lo novamente em uma string.Mas se n não for numérico Number(n) retornará NaN então não vai combinar com o original n

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

Resposta do @CMS:Seu snippet falhou em casos de espaço em branco na minha máquina usando nodejs.Então eu combinei comresposta de @joel para o seguinte:

is_float = function(v) {
    return !isNaN(v) && isFinite(v) &&
        (typeof(v) == 'number' || v.replace(/^\s+|\s+$/g, '').length > 0);
}

Eu testei com aqueles casos que são flutuantes:

var t = [
        0,
        1.2123,
        '0',
        '2123.4',
        -1,
        '-1',
        -123.423,
        '-123.432',
        07,
        0xad,
        '07',
        '0xad'
    ];

e aqueles casos que não são flutuantes (incluindo espaços em branco e objetos/matrizes vazios):

    var t = [
        'hallo',
        [],
        {},
        'jklsd0',
        '',
        "\t",
        "\n",
        ' '
    ];

Tudo funciona como esperado aqui.Talvez isso ajude.

O código-fonte completo para isso pode ser encontrado aqui.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top