Проверка десятичных чисел в JavaScript - IsNumeric ()


2377

Какой самый чистый и эффективный способ проверки десятичных чисел в 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

256
Просто примечание 99,999 - это действительное число во Франции, такое же, как 99,999 в формате uk / us, поэтому, если вы читаете строку, скажем, из формы ввода, тогда 99,999 может быть верным.
записи


79
Десятичная запятая является стандартом во всей Европе и России (кроме Великобритании)
Кальмарий

90
В jQuery 1.7 появилась jQuery.isNumericфункция полезности: api.jquery.com/jQuery.isNumeric
Ates Goral

24
jQuery.isNumericпотерпит неудачу в седьмом тестовом примере OP ( IsNumeric('0x89f') => *false*). Однако я не уверен, согласен ли я с этим тестом.
Тим Ленер

Ответы:


2898

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

// 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содержать числовое значение (я должен был учитывать также экспоненциальную запись и т. Д.), NumberОбъект, в эту функцию можно было передать практически все, я не мог делать предположений о типах, принимая во внимание приведение типов (например, +true == 1;но это trueне следует рассматривать как "numeric").

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

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

PS isNaN & isFinite имеют запутанное поведение из-за принудительного преобразования в число. В ES6 Number.isNaN & Number.isFinite исправят эти проблемы. Имейте это в виду при их использовании.


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

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

Обновление : Angular 4.3 :

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

26
это не работает с другими локалями, где мы используем десятичные запятые, но добавляем `n = n.replace (/, /,". "); ' до возвращения, чтобы исправить это.
Золтан Ленгьель

5
@RobG, это поведение является преднамеренным, 2e308 > Number.MAX_VALUEтак как 2e308 == Infinity. Если вам нужна функция, которая возвращает trueтакже положительные и отрицательные значения бесконечности, проверьте функцию № 2 в наборе тестов . Приветствия.
CMS

39
Кстати, модульные тесты сейчас используются проектом jQuery
CMS

7
jQuery теперь также использует эту реализацию.
RichardTowers

4
Решение здесь состоит в том, чтобы просто использовать JQuery. У них есть еще лучшая реализация этого сейчас: github.com/jquery/jquery/blob/master/src/core.js#L230
Роберт Массайоли

337

Arrrgh! Не слушайте ответы на регулярные выражения. RegEx неприглядно для этого, и я говорю не просто о производительности. Это так легко сделать незаметно, невозможно обнаружить ошибки с помощью регулярного выражения.

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

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

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

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

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

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


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

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

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


28
Это терпит неудачу на пустых строках, например IsNumeric(' '), IsNumeric('\n\t')и т. Д. Все возвращаютсяtrue
Crescent Fresh

29
Он также не будет работать на Numberлитералах, IsNumeric(5) == false;проверяя набор 16тестовых модулей, которые я разместил, эта функция является номером в наборе тестов. stackoverflow.com/questions/18082/…
CMS

20
Я не могу поверить, что никто не указал на использование регулярного выражения (replace) после предупреждения о том, что не следует использовать регулярные выражения ... Конечно, замена пробела проще, чем разбор числа, но все равно определенно "icky".
Патрик М,

1
@ Ориол Это большая проблема ... без исправлений безопасности, выпущенных после этой даты, уход от XP должен быть приоритетом.
Джоэл Коухорн

1
@ Ориол XP или нет, если вы используете IE8 или ниже, вы используете ужасно устаревшее программное обеспечение. Предоставленная XP не может запустить IE9 +, поэтому используйте Chrome или FF. Люди, живущие в прошлом с использованием IE8, являются проклятием существования многих веб-разработчиков. Если бы я мог вернуть время, потраченное на то, чтобы убедиться, что отличный код также работает в IE8 ... Для меня взять код, работающий в FF и Chrome, и установить его для запуска в IE8 - это почти так же практично, взять исполняемый файл Windows 8 и убедившись, что он работает так же в Windows 3.1.
chiliNUT

70

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

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

В одну строку:

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

И проверить это:

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

Я позаимствовал это регулярное выражение у 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

1
// ТАКЖЕ ДОЛЖЕН БЫТЬ ДОБАВЛЕН К ВАШЕМУ ТЕСТУ результаты + = (! IsNumeric ('-')? "Pass": "Fail") + ": IsNumeric ('-') => false \ n"; результаты + = (! IsNumeric ('01 ')? "Pass": "Fail") + ": IsNumeric ('01') => false \ n"; результаты + = (! IsNumeric ('- 01')? "Pass": "Fail") + ": IsNumeric ('- 01') => false \ n"; результаты + = (! IsNumeric ('000')? "Pass": "Fail") + ": IsNumeric ('000') => false \ n";
Дан

что это делает? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
call-me

можно заменить {{0,1} "на«? », поэтому ваше регулярное выражение будет выглядеть так: /^-?\d*\.?\d+$/?
Облако

красиво и просто.
выключатель

53

Yahoo! Пользовательский интерфейс использует это:

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

25
Это больше проверка типа переменной, а не содержимого числа. Он также не будет работать с числами, созданными с помощью new Number(1).
Алекс

4
Как говорит Алекс, это на самом деле не отвечает на поставленный вопрос, так как это не удастся, если o = "1001".
Дело

50
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

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


29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Вернуть trueвместо false.
Oriol

49

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: Как указал Берги , есть другие возможные объекты, которые можно считать числовыми, и было бы лучше, чтобы белый список, чем черный список. Имея это в виду, я бы добавил к критериям.

Я хочу, чтобы моя функция 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>


2
Это, на мой взгляд, самая экранированная функция; последний. Принятый ответ покрывает, вероятно, 99,99% всех случаев, но в этом, вероятно, 100% случаев а) с небольшими накладными расходами.
Самуил

Вы забыли про "99,999" буквальное значение Foating-Point. Это действительный номер во всей Европе, кроме Великобритании
Андрей Хорда

Это не было забыто, это не было чем-то, что я считал числовым в смысле чисел Javascript, ОП также заявилIsNumeric('99,999') => false
Xotic750

34

Да, встроенный 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

18

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


Примечание:! IsNaN (null) == true, поскольку Number (null) == 0
Джонатан Лоновски

if (! (x == null || isNaN (x))) alert ("isNumeric"); // Но это решение принимает 0x40, так что это все еще не то, что хотел оператор.
некоторые

Обратите внимание, что isNaN ("Infinity") === false, что, вероятно, также не то, что вы хотите (но также не произойдет в реальной жизни).
Эрик Хесселинк

16

Начиная с 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это действительное число (гекса)


ОП требует действительного десятичного числа, поэтому jQuery isNumeric не подходит. Это также терпит неудачу для очень больших чисел.
RobG

13

Это может быть сделано без RegExp как

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

5
Если мы используем ==, он вернет true даже для чисел, представленных в виде строк. Таким образом, «42» будет считаться действительным числом в случае «==» и будет считаться недействительным в случае ===
Aquatic

это возвращает true для "-0.", "-.0", ".0" и "0."
Янус Троелсен


8
return (input - 0) == input && input.length > 0;

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

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

Работало нормально.


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

7

Единственная проблема, с которой я столкнулся при ответе @ CMS - исключение NaNи Infinity, которые являются полезными числами для многих ситуаций. Один из способов проверить 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 довольно близок к другому элегантному ответу , но обрабатывает шестнадцатеричные и другие строковые представления чисел.


6

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

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

К сожалению, это своего рода STRICT числовая проверка, которая не будет работать для любой строки, содержащей только числовые буквы, например, «0» и т. Д.
Арман Макхитариан

6

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

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

Положительные шестнадцатеричные числа начинаются с, 0xа отрицательные шестнадцатеричные числа начинаются с -0x. Положительные октавные числа начинаются с, 0а отрицательные октавные числа начинаются с -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));
}

6

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

function isNumeric(n) {

    return parseFloat(n) == n;
}

Да, я тоже пришел к такому выводу. Мне также очень нравится, как массивы обрабатываются с помощью этого метода; массив с одним значением считается этим значением, но все остальное терпит неудачу: IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; но я думаю, это дело вкуса!
Марк Бирбек

4

Пара тестов для добавления:

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

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

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

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

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

4

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

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

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


4

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

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

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


2
Осторожно, унарный '+' вызовет valueOf () для объекта - смотрите это jsfiddle . Также это не помогает для ведущих пробелов, как и ведущий ответ.
наушник

3

Мое решение,

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

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


Это регулярное выражение будет менее запутанным, если вы не будете без необходимости избегать символов, используйте ?для {0,1}и \dдля [0-9]. Кроме того, +а затем оборачивая его (?:){0,1}, вы можете также использовать *и забыть (не) группы захвата.
Алекс


3

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

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

Разъяснение:

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

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

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


4
используйте на свой страх и риск, без гарантий я не буду использовать код, в котором автор не уверен;)
alex

1
@ Алекс, по крайней мере, есть свое мнение о вещах. Не просто критиковать все время.
Стюарт Мбофана

3

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

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

3

Чтобы проверить, содержит ли переменная действительное число, а не просто строку, которая выглядит как число, 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

1
Я предполагаю, что многие люди обращаются к этому вопросу для анализа пользовательского ввода, который обычно является строкой . Этот ответ в тех случаях не удался, как вы правильно перечислили в примерах, напримерNumber.isFinite('0') -> false
Майкл Харен

Ты совершенно прав. Я пытался сделать это ясно впереди.
adius

3
function inNumeric(n){
   return Number(n).toString() === n;
}

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


Хотя этот фрагмент кода может решить вопрос, в том числе объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин, по которым вы предлагаете код. Также постарайтесь не переполнять ваш код пояснительными комментариями, так как это снижает удобочитаемость кода и пояснений!
До свидания, StackExchange

2

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

Следует отметить, что предполагается, что «.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');
}

Идея здесь состоит в том, что каждое число или целое число имеет одно «каноническое» строковое представление, и каждое неканоническое представление должно быть отклонено. Таким образом, мы приводим число и обратно и видим, является ли результат исходной строкой.

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

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

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

2

knockoutJs Встроенные функции проверки библиотеки

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

1) номер

self.number = ko.observable(numberValue).extend ({число: правда}) ;

Прецедент

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).extend ({digit: true}) ;

Прецедент

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).extend ({мин: 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

2

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

http://codesheet.org/codesheet/x1kI7hAD

<input type="text" name="date" value="" pattern="[0-9]){1,2}(\.){1}([0-9]){2}" maxlength="6" placeholder="od npr.: 16.06" onchange="date(this);" />

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

2

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

Ничего особенного, но мы можем использовать булев конструктор

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.