Вопрос

Какой самый чистый и эффективный способ проверки десятичных чисел в JavaScript?

Бонусные баллы за:

  1. Ясность.Решение должно быть чистым и простым.
  2. Кроссплатформенный.

Тестовые примеры:

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
Это было полезно?

Решение

Ответ @Joel's это довольно близко, но это приведет к сбою в следующих случаях:

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

Некоторое время назад мне пришлось реализовать IsNumeric функция, позволяющая выяснить, содержит ли переменная числовое значение, независимо от его типа, это может быть String содержащий числовое значение (я должен был учитывать также экспоненциальную нотацию и т.д.), a Number объект, практически все, что угодно, могло быть передано этой функции, я не мог делать никаких предположений о типе, заботясь о приведении типов (например. +true == 1; но true не следует рассматривать как "numeric").

Я думаю, стоит поделиться этим набором +30 модульных тестов сделано для многочисленных реализаций функций, а также делюсь той, которая проходит все мои тесты:

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

P.S. исНаН & Конечен сбивающее с толку поведение из-за принудительного преобразования в число.В ES6, Номер.isNaN & Число.Является конечным это устранило бы эти проблемы.Имейте это в виду при их использовании.


Обновить : Вот как jQuery делает это сейчас (2.2-стабильный):

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

Обновить : Угловой 4.3:

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

Другие советы

Аррргх!Не слушайте ответы из регулярных выражений.Регулярное выражение неприлично для этого, и я говорю не только о производительности.С помощью вашего регулярного выражения так легко сделать незаметные ошибки, которые невозможно заметить.

Если вы не можете использовать isNaN(), это должно работать намного лучше:

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

Вот как это работает:

Тот Самый (input - 0) expression заставляет JavaScript выполнять принудительное ввод типа для вашего входного значения;сначала оно должно быть интерпретировано как число для операции вычитания.Если это преобразование в число завершится неудачей, выражение приведет к NaN.Это числовой затем результат сравнивается с исходным значением, которое вы передали.Поскольку левая сторона теперь числовая, снова используется принудительное ввод типа.Теперь, когда входные данные с обеих сторон были приведены к одному и тому же типу из одного и того же исходного значения, вы могли бы подумать, что они всегда должны быть одинаковыми (всегда true).Однако существует специальное правило, которое гласит NaN никогда не равно NaN, и поэтому значение, которое не может быть преобразовано в число (и только значения, которые не могут быть преобразованы в числа), приведет к значению false.

Проверка длины предназначена для особого случая, связанного с пустыми строками.Также обратите внимание, что это не выполняется в вашем тесте 0x89f, но это потому, что во многих средах это обычный способ определения числового литерала.Если вы хотите отследить этот конкретный сценарий, вы могли бы добавить дополнительную проверку.Еще лучше, если это ваша причина не использовать isNaN() затем просто оберните свою собственную функцию вокруг isNaN() это также может привести к дополнительной проверке.

Подводя итог, если вы хотите знать, можно ли преобразовать значение в число, на самом деле попробуйте преобразовать его в число.


Я вернулся и провел кое-какие исследования для почему строка с пробелами не имела ожидаемого результата, и я думаю, что теперь я это понял:пустая строка принудительно преобразуется в 0 вместо того , чтобы NaN.Простое обрезание строки перед проверкой длины поможет справиться с этим случаем.

Запуск модульных тестов с новым кодом приводит к сбою только для бесконечных и логических литералов, и единственный раз, когда должна возникнуть проблема, - это если вы генерируете код (действительно, кто будет вводить литерал и проверять, числовой ли он?Ты должен знать), и это был бы какой-то странный код для генерации.

Но, опять же, единственная причина когда-либо использовать это, - это если по какой-то причине вам нужно избегать isNaN().

Этот способ, кажется, работает хорошо:

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

И чтобы проверить это:

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

Я позаимствовал это регулярное выражение у http://www.codetoad.com/javascript/isnumeric.asp.Объяснение:

/^ 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!Пользовательский интерфейс использует это:

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

Это также работает для чисел типа 0x23.

Принятый ответ провалил ваш тест № 7, и я думаю, это потому, что вы передумали.Итак, это ответ на принятый ответ, с которым у меня были проблемы.

Во время некоторых проектов мне нужно было проверить некоторые данные и быть как можно более уверенным, что это числовое значение javascript, которое может быть использовано в математических операциях.

jQuery и некоторые другие библиотеки javascript уже включают такую функцию, обычно вызываемую isNumeric.Существует также публикация в stackoverflow это было широко принято в качестве ответа, той же общей процедуры, которую используют вышеупомянутые библиотеки.

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

Во-первых, приведенный выше код вернул бы значение true, если бы аргументом был массив длиной 1, и этот единственный элемент имел тип, который по приведенной выше логике считается числовым.На мой взгляд, если это массив, то он не числовой.

Чтобы облегчить эту проблему, я добавил проверку на исключение массивов из логики

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

Конечно, вы также могли бы использовать Array.isArray, jquery $.isArray или прототип Object.isArray вместо того, чтобы Object.prototype.toString.call(n) !== '[object Array]'

Моя вторая проблема заключалась в том, что отрицательные шестнадцатеричные целочисленные литеральные строки ("-0xA" -> -10) не считались числовыми.Однако положительные шестнадцатеричные целочисленные литеральные строки ("0xA" -> 10) обрабатывались как числовые.Мне нужно было, чтобы оба они были действительными числовыми.

Затем я изменил логику, чтобы учесть это.

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

Если вы беспокоитесь о создании регулярного выражения при каждом вызове функции, то вы могли бы переписать его внутри замыкания, что-то вроде этого

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

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

Затем я принял CMSs +30 тестовых примеров и клонировал тестирование на jsfiddle добавлены мои дополнительные тестовые примеры и мое вышеописанное решение.

Это может не заменить широко принятый / используемый ответ, но если это больше того, что вы ожидаете в качестве результатов от вашей IsNumeric функции, то, надеюсь, это окажет некоторую помощь.

Редактировать: Как было указано Bergi, существуют и другие возможные объекты, которые можно было бы считать числовыми, и было бы лучше внести их в белый список, чем в черный.Имея это в виду, я бы добавил к критериям.

Я хочу, чтобы моя isnumericфункция учитывала только числа или строки

Имея это в виду, было бы лучше использовать

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

Протестируйте решения

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>

Да, встроенный isNaN(object) это будет намного быстрее, чем любой синтаксический анализ регулярных выражений, потому что он встроенный и компилируется, а не интерпретируется на лету.

Хотя результаты несколько отличаются от того, что вы ищете (попробуй это):

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

Используйте эту функцию isNaN.Я верю, что если вы проверите на !isNaN(yourstringhere) это прекрасно работает в любой из этих ситуаций.

Начиная с jQuery 1.7, вы можете использовать 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

Просто обратите внимание, что в отличие от того, что вы сказали, 0x89f является допустимым числом (hexa)

Это может быть сделано без регулярного выражения, как

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

Я понимаю, что в первоначальном вопросе не упоминался jQuery, но если вы используете jQuery, вы можете сделать:

$.isNumeric(val)

Просто.

https://api.jquery.com/jQuery.isNumeric/ (по состоянию на jQuery 1.7)

Если я не ошибаюсь, это должно соответствовать любому допустимому значению числа JavaScript, исключая константы (Infinity, NaN) и операторы знака +/- (поскольку, насколько мне известно, они на самом деле не являются частью числа, это отдельные операторы):

Мне это было нужно для токенизатора, где отправка номера в JavaScript для оценки была невозможна...Это определенно не самое короткое из возможных регулярных выражений, но я считаю, что оно улавливает все тонкости числового синтаксиса 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

Допустимые номера будут включать:

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

Недопустимые числа были бы

 - 00e1
 - 01e1
 - 00.0
 - 00x0
 - .
 - .e0
return (input - 0) == input && input.length > 0;

у меня это не сработало.Когда я ввел оповещение и протестировал, input.length был undefined.Я думаю, что нет свойства для проверки целочисленной длины.Итак, что я сделал, так это

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

Это сработало нормально.

Для меня это лучший способ:

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

Единственная проблема, которая у меня возникла с @CMS ответ является исключением NaN и Бесконечность, которые являются полезными числами для многих ситуаций.Один из способов проверить наличие NaNэто проверка наличия числовых значений, которые не равны самим себе, NaN != NaN!Итак , на самом деле есть 3 теста , с которыми вы хотели бы разобраться ...

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

Мой isComparableNumber довольно близок к другому элегантному ответ, но обрабатывает шестнадцатеричные и другие строковые представления чисел.

Целочисленное значение может быть проверено с помощью:

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

Этот способ проще и быстрее!Все тесты проверены!

Вот немного улучшенная версия (вероятно, самый быстрый способ), которую я использую вместо точного варианта jQuery, я действительно не знаю, почему они не используют этот:

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

Недостатком версии jQuery является то, что если вы передаете строку с начальными цифрами и конечными буквами, например "123abc" тот самый parseFloat | parseInt извлечет числовую дробь и вернет 123, НО второй предохранитель isFinite все равно это провалится.С унарным + оператор it умрет при первой же защите, поскольку + выдает NaN для таких гибридов :) Небольшая производительность, но, я думаю, солидный семантический выигрыш.

Я хотел бы добавить следующее:

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

Положительные шестнадцатеричные числа начинаются с 0x а отрицательные шестнадцатеричные числа начинаются с -0x.Положительные числа oct начинаются с 0 и отрицательные числа oct начинаются с -0.Этот вариант учитывает большую часть того, что уже было упомянуто, но включает шестнадцатеричные и восьмеричные числа, отрицательные научные, бесконечность и удалил десятичные научные (4e3.2 недействителен).

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

Нужно добавить пару тестов:

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

Я придумал вот что:

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

Решение охватывает:

  • Необязательный отрицательный знак в начале
  • Один ноль, или одна или несколько цифр, не начинающихся с 0, или ничего, пока за ними следует точка
  • Точка, за которой следует 1 или более чисел

Мое решение,

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

Кажется, это работает в любой ситуации, но я могу ошибаться.

Это должно сработать.Некоторые из функций, представленных здесь, имеют недостатки, также должны быть быстрее, чем любая другая функция здесь.

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

Объясненный:

Создайте свою копию, затем преобразуйте число в значение с плавающей точкой, затем сравните себя с исходным числом, если оно все еще является числом (будь то целое число или с плавающей точкой), и соответствует исходному числу, это означает, что это действительно число.

Он работает как с числовыми строками, так и с простыми числами.Не работает с шестнадцатеричными числами.

Предупреждение:используйте на свой страх и риск, никаких гарантий.

Ни один из ответов не возвращается false для пустых строк это исправлено...

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

Чтобы проверить, содержит ли переменная действительное число, а не просто строку, которая выглядит как число. просто строка, которая выглядит как число, Number.isFinite(value) может быть использован.

Это часть языка с тех пор, как ES2015

Примеры:

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

Я использую более простое решение:

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

Я понимаю, что на этот вопрос отвечали много раз, но следующий - достойный кандидат, который может быть полезен в некоторых сценариях.

следует отметить, что предполагается, что '.42' - это НЕ число, а '4.' - ЭТО НЕ число, поэтому это следует принимать во внимание.

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

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

Тот Самый isDecimal проходит следующий тест:

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

Идея здесь заключается в том, что каждое число или integer имеет одно "каноническое" строковое представление, и каждое неканоническое представление должно быть отклонено.Итак, мы приводим к числу и обратно и смотрим, является ли результат исходной строкой.

Будут ли эти функции полезны для вас, зависит от варианта использования.Одна из особенностей заключается в том, что разные строки представляют разные числа (если оба проходят isNumber() тест).

Это актуально, напримердля чисел в качестве имен свойств объекта.

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

Функции проверки встроенной библиотеки KnockoutJS

Расширяя его, поле проверяется

1) число

self.number = ko.observable(numberValue).расширить({ число:верно});

Тестовый кейс

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) цифра

self.number = ko.observable(numberValue).расширить({ цифра:верно});

Тестовый кейс

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) минимальный и максимальный

self.number = ko.observable(numberValue).продлить({ мин:5}).расширить({ макс:10});

Это поле принимает только значение от 5 до 10

Тестовый кейс

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

Вы можете во многом минимизировать эту функцию, а также реализовать ее с помощью пользовательского регулярного выражения для отрицательных значений или пользовательских диаграмм:

$('.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;
}

Если n - числовое значение Number(n) вернет числовое значение и toString() превратит его обратно в строку.Но если n не является числовым Number(n) вернется NaN так что это не будет соответствовать оригиналу n

Я думаю, что функция parseFloat может выполнить всю работу здесь.Приведенная ниже функция проходит все тесты на этой странице, включая isNumeric(Infinity) == true:

function isNumeric(n) {

    return parseFloat(n) == n;
}

Ответ @CMS:Ваш фрагмент не удался из-за пробелов на моем компьютере с использованием nodejs.Поэтому я объединил это с Ответ @joel's к следующему:

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

Я объединил это с теми случаями, которые являются плавающими:

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

и те случаи, в которых нет плавающих значений (включая пустые пробелы и объекты / массивы):

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

Здесь все работает так, как и ожидалось.Может быть, это поможет.

Полный исходный код для этого можно найти здесь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top