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

Какой самый чистый и эффективный способ проверки десятичных чисел в 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
20.08.2008 14:21:13
Просто примечание 99,999 - это действительное число во Франции, такое же, как 99,999 в формате uk / us, поэтому, если вы читаете строку, скажем, из формы ввода, тогда 99,999 может быть верным.
Re0sless 20.08.2008 14:31:46
powtac 23.11.2009 18:05:06
Десятичная запятая является стандартом во всей Европе и России (кроме Великобритании)
Calmarius 16.02.2011 14:29:25
В jQuery 1.7 появилась jQuery.isNumericфункция полезности: api.jquery.com/jQuery.isNumeric
Ates Goral 16.11.2011 20:04:53
jQuery.isNumericпотерпит неудачу в седьмом тестовом примере OP ( IsNumeric('0x89f') => *false*). Однако я не уверен, согласен ли я с этим тестом.
Tim Lehner 27.08.2012 16:42:48
30 ОТВЕТОВ
РЕШЕНИЕ

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

// 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));
}
2891
1.06.2018 15:21:11
это не работает с другими локалями, где мы используем десятичные запятые, но добавляем `n = n.replace (/, /,". "); ' до возвращения, чтобы исправить это.
Zoltan Lengyel 26.04.2011 02:14:28
@RobG, это поведение является намеренным, 2e308 > Number.MAX_VALUEтак как 2e308 == Infinity. Если вам нужна функция, которая возвращает trueтакже положительные и отрицательные значения бесконечности, проверьте функцию № 2 в наборе тестов . Приветствия.
CMS 24.06.2011 18:30:34
Кстати, модульные тесты сейчас используются проектом jQuery
CMS 31.01.2012 19:13:56
jQuery теперь также использует эту реализацию.
RichardTowers 1.12.2012 11:33:20
Решение здесь состоит в том, чтобы просто использовать JQuery. У них есть еще лучшая реализация этого сейчас: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli 6.10.2013 04:44:48

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

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
69
14.03.2020 06:54:04
// ТАКЖЕ ДОЛЖЕН БЫТЬ ДОБАВЛЕН К ВАШЕМУ ТЕСТУ результаты + = (! 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";
Dan 28.01.2010 01:47:01
что это делает? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
call-me 2.09.2016 23:42:43
можно заменить "{0,1}" на "?", так что ваше регулярное выражение будет выглядеть так: /^-?\d*\.?\d+$/?
Cloud 14.10.2016 10:20:13
красиво и просто.
the-breaker 14.03.2020 06:55:40

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

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

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

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

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

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

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

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
5.01.2018 13:02:03

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

18
10.02.2016 16:19:51
Примечание:! IsNaN (null) == true, поскольку Number (null) == 0
Jonathan Lonowski 15.10.2008 04:50:47
if (! (x == null || isNaN (x))) alert ("isNumeric"); // Но это решение принимает 0x40, так что это все еще не то, что хотел оператор.
some 15.12.2008 04:58:18
Обратите внимание, что isNaN ("Infinity") === false, что, вероятно, также не то, что вы хотите (но также не произойдет в реальной жизни).
Erik Hesselink 10.02.2010 15:13:50

Да, встроенный 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
34
8.08.2013 14:39:20

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

function IsNumeric(data){
    return parseFloat(data)==data;
}
13
22.08.2008 15:08:05
Если мы используем ==, он вернет true даже для чисел, представленных в виде строк. Таким образом, «42» будет считаться действительным числом в случае «==» и будет считаться недействительным в случае ===
Aquatic 25.11.2009 18:38:44
это возвращает true для "-0.", "-.0", ".0" и "0."
Janus Troelsen 28.09.2012 22:16:44

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 ().

335
28.01.2015 20:47:01
Это терпит неудачу на пустых строках, например IsNumeric(' '), IsNumeric('\n\t')и т. Д., Все возвращаютсяtrue
Crescent Fresh 2.12.2009 04:36:06
Он также не будет работать на Numberлитералах, IsNumeric(5) == false;проверяя набор 16тестовых модулей, которые я разместил, эта функция является номером в наборе тестов. stackoverflow.com/questions/18082/…
CMS 2.12.2009 05:52:38
Я не могу поверить, что никто не указал на использование регулярного выражения (replace) после предупреждения о неиспользовании регулярных выражений ... Конечно, замена пробела проще, чем разбор числа, но все равно определенно "icky".
Patrick M 20.06.2013 14:41:58
@ Oriol Это большая проблема ... без исправлений безопасности, выпущенных после этой даты, уход от XP должен быть приоритетом.
Joel Coehoorn 20.10.2013 04:38:12
@ Ориол XP или нет, если вы используете IE8 или ниже, вы используете ужасно устаревшее программное обеспечение. Предоставленная XP не может запустить IE9 +, поэтому используйте Chrome или FF. Люди, живущие в прошлом с использованием IE8, являются проклятием существования многих веб-разработчиков. Если бы я мог вернуть время, потраченное на то, чтобы убедиться, что отличный код также работает в IE8 ... Для меня взять код, работающий в FF и Chrome, и установить его для запуска в IE8 - это почти так же практично, взять исполняемый файл Windows 8 и убедившись, что он работает так же в Windows 3.1.
chiliNUT 20.04.2014 03:43:08

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

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}
53
2.04.2013 00:39:05
Это больше проверка типа переменной, а не содержимого числа. Он также не будет работать с числами, созданными с помощью new Number(1).
alex 23.06.2011 05:33:17
Как говорит Алекс, это на самом деле не отвечает на поставленный вопрос, так как это не удастся, если o = "1001".
Case 25.01.2013 23:49:26
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

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

50
16.06.2012 13:01:37
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Вернуть trueвместо false.
Oriol 7.09.2013 16:29:15

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

isNumber : function(v){
   return typeof v === 'number' && isFinite(v);
}
6
28.05.2010 11:30:26
К сожалению, это своего рода STRICT числовая проверка, которая не будет работать для любой строки, содержащей только числовые буквы, например, «0» и т. Д.
Arman McHitarian 20.05.2013 16:36:43

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

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

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

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

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

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

3
7.08.2013 21:59:27
используйте на свой страх и риск, без гарантий я не буду использовать код, в котором автор не уверен;)
alex 7.08.2013 22:00:00
@ Алекс, по крайней мере, есть свое мнение о вещах. Не просто критиковать все время.
Stewart Mbofana 28.01.2014 08:35:19

Следующее может работать как хорошо.

function isNumeric(v) {
         return v.length > 0 && !isNaN(v) && v.search(/[A-Z]|[#]/ig) == -1;
   };
-4
2.12.2012 10:14:08
return (input - 0) == input && input.length > 0;

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

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

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

8
5.01.2018 13:04:36

Мое решение,

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

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

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

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

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

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

4
6.01.2013 18:36:05

@Zoltan Lengyel комментарий «других локалей» (26 апреля в 2:14) в ответе @CMS Dec (2 '09 в 5:36):

Я бы порекомендовал тестирование на typeof (n) === 'string':

    function isNumber(n) {
        if (typeof (n) === 'string') {
            n = n.replace(/,/, ".");
        }
        return !isNaN(parseFloat(n)) && isFinite(n);
    }

Это расширяет рекомендацию Zoltans, чтобы иметь возможность тестировать не только «локальные числа», isNumber('12,50')но и «чистые» числа isNumber(2011).

-2
10.02.2016 16:19:21

Ну, я использую тот, который я сделал ...

Это работает до сих пор:

function checkNumber(value) {
    if ( value % 1 == 0 )
        return true;
    else
        return false;
}

Если вы обнаружите какие-либо проблемы с этим, скажите мне, пожалуйста.

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

-3
19.03.2012 19:00:18
Как насчет 1.5? Кроме того, в теле функции много избыточного кода. Вы должны напрямую вернуть результат выражения, который будет логическим.
alex 7.08.2013 22:06:44

Если я не ошибаюсь, это должно соответствовать любому действительному значению числа 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
10.02.2016 16:14:12

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

function isNumber(num) {
    return parseFloat(num).toString() == num
}
3
16.06.2012 12:25:25
это потерпит неудачу на чем-либо с лишними нулями в конце. Пример: «10.0»
Janus Troelsen 28.09.2012 22:13:33

Здесь я собрал «хорошие» с этой страницы и поместил их в простой тестовый шаблон, который вы сможете оценить самостоятельно.

Для новичков console.logвстроенная функция (доступна во всех современных браузерах) позволяет выводить результаты в консоль JavaScript (копаться, вы ее найдете), а не выводить на свою HTML-страницу.

var isNumeric = function(val){
    // --------------------------
    // Recommended
    // --------------------------

    // jQuery - works rather well
    // See CMS's unit test also: http://dl.getdropbox.com/u/35146/js/tests/isNumber.html
    return !isNaN(parseFloat(val)) && isFinite(val);

    // Aquatic - good and fast, fails the "0x89f" test, but that test is questionable.
    //return parseFloat(val)==val;

    // --------------------------
    // Other quirky options
    // --------------------------
    // Fails on "", null, newline, tab negative.
    //return !isNaN(val);

    // user532188 - fails on "0x89f"
    //var n2 = val;
    //val = parseFloat(val);
    //return (val!='NaN' && n2==val);

    // Rafael - fails on negative + decimal numbers, may be good for isInt()?
    // return ( val % 1 == 0 ) ? true : false;

    // pottedmeat - good, but fails on stringy numbers, which may be a good thing for some folks?
    //return /^-?(0|[1-9]\d*|(?=\.))(\.\d+)?$/.test(val);

    // Haren - passes all
    // borrowed from http://www.codetoad.com/javascript/isnumeric.asp
    //var RE = /^-{0,1}\d*\.{0,1}\d+$/;
    //return RE.test(val);

    // YUI - good for strict adherance to number type. Doesn't let stringy numbers through.
    //return typeof val === 'number' && isFinite(val);

    // user189277 - fails on "" and "\n"
    //return ( val >=0 || val < 0);
}

var tests = [0, 1, "0", 0x0, 0x000, "0000", "0x89f", 8e5, 0x23, -0, 0.0, "1.0", 1.0, -1.5, 0.42, '075', "01", '-01', "0.", ".0", "a", "a2", true, false, "#000", '1.2.3', '#abcdef', '', "", "\n", "\t", '-', null, undefined];

for (var i=0; i<tests.length; i++){
    console.log( "test " + i + ":    " + tests[i] + "    \t   " + isNumeric(tests[i]) );
}
-3
10.02.2016 16:18:15

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

16
18.02.2013 09:01:43
ОП требует действительного десятичного числа, поэтому jQuery isNumeric не подходит. Это также терпит неудачу для очень больших чисел.
RobG 2.11.2015 21:21:50

Принятый ответ не прошел тест №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>
  
48
5.01.2018 12:56:31
Это, на мой взгляд, самая экранированная функция; последний. Принятый ответ покрывает, вероятно, 99,99% всех случаев, но в этом, вероятно, 100% а) случаев с небольшими накладными расходами.
Samuel 7.01.2014 03:59:31
Вы забыли про "99,999" буквальное значение Foating-Point. Это действительный номер во всей Европе, кроме Великобритании
Andrii Horda 28.01.2016 14:59:08
Это не было забыто, это не было чем-то, что я считал числовым в смысле чисел Javascript, ОП также заявилIsNumeric('99,999') => false
Xotic750 28.01.2016 18:50:47

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 ({цифра: правда}) ;

Прецедент

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
10.02.2016 16:17:14

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

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",
        ' '
    ];

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

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

1
23.05.2017 12:34:53

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

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

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

4
20.05.2013 16:48:18
Осторожно, унарный '+' вызовет valueOf () для объекта - смотрите это jsfiddle . Также это не помогает для ведущих пробелов, как и ведущий ответ.
earcam 24.09.2013 23:34:21

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

7
5.01.2018 13:03:22

Я нашел простое решение, вероятно, не лучшее, но оно работает нормально :)

Итак, что я делаю дальше, я анализирую строку в Int и проверяю, совпадает ли размер длины новой переменной, которая теперь является типом int, с длиной исходной строковой переменной. Логически, если размер одинаков, это означает, что строка полностью анализируется в int, и это возможно, только если строка «сделана» только из чисел.

var val=1+$(e).val()+'';
var n=parseInt(val)+'';
if(val.length == n.length )alert('Is int');

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

Примечание: добавление 1+ на e.val, чтобы начальный ноль не был удален.

0
9.07.2013 23:19:24

Я запустил следующее ниже, и он проходит все тестовые случаи ...

Он использует другой способ parseFloatи Numberобрабатывать их входные данные ...

function IsNumeric(_in) {
    return (parseFloat(_in) === Number(_in) && Number(_in) !== NaN);
}
2
5.01.2018 12:58:48
Я не пробовал это, но просто совет: вы можете уменьшить это, чтобы просто вернуть ifвыражение, напримерreturn parseFloat...
Michael Haren 27.09.2013 17:33:55
@ Майкл Харен, глупый я, я только что видел эту ссылку http://dl.dropboxusercontent.com/u/35146/js/tests/isNumber.htmlв самом высоком отклике (тот, о 30+ тестовых случаях), многое объясняет ...
Aaron Gong 27.09.2013 17:49:17
Это неправильно, вы не можете сравнить с NaN с ==, ===, !=или !==, он всегда возвращает ложь.
Alexis Wilke 15.12.2014 23:38:27
Хитрость в NaN заключается в том, что он не одинаков для каждого значения JavaScript, включая его самого. Так anythingAtAll === NaNложно и anythingAtAll !== NaNверно. Вы проверяете NaN, сравнивая значение с самим собой: x !== xtrue, если x равен NaN, и false в противном случае.
jkdev 14.07.2015 23:09:18
@jkdev Вы также можете использовать isNaN(NaN)который вернет истину. Это встроенная функция для JavaScript. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Jacob Gunther 9.11.2017 04:06:02

Кажется, что следующее работает хорошо для многих случаев:

function isNumeric(num) {
    return (num > 0 || num === 0 || num === '0' || num < 0) && num !== true && isFinite(num);
}

Это построено поверх этого ответа (и для этого ответа): https://stackoverflow.com/a/1561597/1985601

1
23.05.2017 12:18:30