在Javascript中验证十进制数-IsNumeric()

2561

在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

272
请注意,在法国,99,999是一个有效的数字,它与英式/美式格式中的99.999是相同的。因此,如果您从输入表单中读取字符串,则99,999可能是真实的。请注意,这是一条翻译,不包括任何额外的解释或内容。 - Re0sless
5
请查看这篇文章和精彩评论 - powtac
82
十进制逗号是整个欧洲和俄罗斯(英国除外)的标准。 - Calmarius
93
jQuery 1.7 引入了 jQuery.isNumeric 工具函数:http://api.jquery.com/jQuery.isNumeric/。 - Ates Goral
26
jQuery.isNumeric 无法通过 OP 的第七个测试用例 (IsNumeric('0x89f') => *false*)。然而,我不确定是否同意这个测试用例。 - Tim Lehner
显示剩余5条评论
53个回答

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

我认为我的代码很完美...

/**
 * @param {string} s
 * @return {boolean}
 */
var isNumber = function(s) {
    return s.trim()!=="" && !isNaN(Number(s));
};


2

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

这段代码的作用是判断一个值是否为数字类型。我们可以使用Boolean构造函数来简化代码。


2

通过利用语言的动态类型检查,可以实现简单清晰的解决方案:

Original Answer翻译成"最初的回答"

function IsNumeric (string) {
   if(string === ' '.repeat(string.length)){
     return false
   }
   return string - 0 === string * 1
}


如果您不关心空格,可以删除那个"if"。
请参见下面的测试用例。
最初的回答:如果你不在意空格,你可以删除那个"if"。
看下面的测试案例。

function IsNumeric (string) {
   if(string === ' '.repeat(string.length)){
      return false
   }
   return string - 0 === string * 1
}


console.log('-1' + ' → ' + IsNumeric('-1'))    
console.log('-1.5' + ' → ' + IsNumeric('-1.5')) 
console.log('0' + ' → ' + IsNumeric('0'))     
console.log('0.42' + ' → ' + IsNumeric('0.42'))   
console.log('.42' + ' → ' + IsNumeric('.42'))    
console.log('99,999' + ' → ' + IsNumeric('99,999'))
console.log('0x89f' + ' → ' + IsNumeric('0x89f'))  
console.log('#abcdef' + ' → ' + IsNumeric('#abcdef'))
console.log('1.2.3' + ' → ' + IsNumeric('1.2.3')) 
console.log('' + ' → ' + IsNumeric(''))    
console.log('33 ' + ' → ' + IsNumeric('33 '))


2

knockoutJs内置库验证函数

通过扩展字段进行验证

1) 数字

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

测试用例

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({ min: 5}).extend({ max: 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

您可以采用多种方式来最小化此功能,还可以使用自定义正则表达式处理负值或自定义图表进行实现:

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

1

可以使用类型检查库,例如https://github.com/arasatasaygin/is.js或者从中提取检查代码片段(https://github.com/arasatasaygin/is.js/blob/master/is.js#L131):

is.nan = function(value) {    // NaN is number :) 
  return value !== value;
};
 // is a given value number?
is.number = function(value) {
    return !is.nan(value) && Object.prototype.toString.call(value) === '[object Number]';
};

一般而言,如果您需要验证参数类型(在函数调用的入口点),您可以使用符合JSDOC标准的合同(https://www.npmjs.com/package/bycontract):
/**
 * This is JSDOC syntax
 * @param {number|string} sum
 * @param {Object.<string, string>} payload
 * @param {function} cb
 */
function foo( sum, payload, cb ) {
  // Test if the contract is respected at entry point
  byContract( arguments, [ "number|string", "Object.<string, string>", "function" ] );
}
// Test it
foo( 100, { foo: "foo" }, function(){}); // ok
foo( 100, { foo: 100 }, function(){}); // exception

1

@CMS的回答: 在我的机器上使用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
以下对许多情况似乎都有效:

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

这是在这个答案的基础上构建的(也适用于这个答案): https://dev59.com/3nVD5IYBdhLWcg3wU56H#1561597


1
function isNumber(n) {
    return (n===n+''||n===n-0) && n*0==0 && /\S/.test(n);
}

说明:

(n===n-0||n===n+'') 验证 n 是数字还是字符串 (不包括数组、布尔值、日期、null 等)。你可以将 (n===n-0 || n===n+'') 替换为 n!==undefined && n!==null && (n.constructor===Number || n.constructor===String):更快但不够简洁。

n*0==0 验证 n 是否为有限数字,与 isFinite(n) 相同。如果你需要检查表示负十六进制的字符串,只需将 n*0==0 替换为类似于 n.toString().replace(/^\s*-/,'')*0==0 的内容。
当然,这会稍微花费一点时间,所以如果您不需要它,请不要使用它。

/\S/.test(n)会丢弃空字符串或仅包含空格的字符串(必要的,因为在这种情况下isFinite(n)或n*0==0返回一个false positive)。您可以通过使用(n!=0||/0/.test(n))代替/\S/.test(n)来减少对.test(n)的调用次数,或者您可以使用稍微快一些但不太简洁的测试,例如(n!=0||(n+'').indexOf('0')>=0):微小的改进。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接