在JavaScript中验证十进制数字最干净、最有效的方法是什么?

奖励积分:

清晰解决方案应干净简单。跨平台。

测试用例:

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

当前回答

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

这里的一切都按预期进行。也许这有帮助。

这里可以找到完整的源代码。

其他回答

使用函数isNaN。我相信如果你测试!是NaN(你的字符串),它适用于任何这些情况。

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

解释:

(n===n-0||n===n+'')验证n是数字还是字符串(丢弃数组、布尔值、日期、空值…)。您可以用n替换(n===n-0|| n===n+'')==未定义&&n==null&&(n.constructor==数字||n.constructor==字符串):明显更快,但不那么简洁。

n*0==0验证n是否是有限数,正如isFinite(n)所做的那样。如果您需要检查表示负十六进制的字符串,只需将n*0==0替换为类似于n.toString().replace(/^\s*-/,'')*0==0。当然,它需要一点钱,所以如果你不需要它,就不要使用它。

/\S/.test(n)丢弃空字符串或只包含空格的字符串(这是必要的,因为在这种情况下isFinite(n)或n*0==0返回假阳性)。您可以使用(n!=0||/0/.test(n))而不是\\S/.test(n)来减少对.test(n)的调用次数,也可以使用稍快但不太简洁的测试,例如(n!=0 | |(n+'').indexOf('0')>=0):微小的改进。

如果typeof n==“string”,则需要检查空/未定义条件并删除逗号(对于美国数字格式)。

function isNumeric(n)
{
    if(n === null || typeof n === 'undefined')
         return false;

    if(typeof n === 'string')
        n = n.split(',').join('');

    return !isNaN(parseFloat(n)) && isFinite(n);
}

https://jsfiddle.net/NickU/nyzeot03/3/

如果您希望让数值函数的预测值隐式严格(例如,不解析字符串),那么这应该会奏效。

function isNumeric(n, parse) {
    var t = typeof(n);
    if (parse){
        if (t !== 'number' && t !=='string') return false;
        return !isNaN(parseFloat(n)) && isFinite(n);
    }else{
        if (t !== 'number') return false;
        return !isNaN(n) && isFinite(n) && !_.isString(n);
    }
}

function isInteger(n, parse) {    
    return isNumeric(n, parse) && n % 1 === 0;
}

function isFloat(n, parse) {
    return isNumeric(n, parse) && n % 1 !== 0;
}

如果您希望代码解析字符串,那么只需在parse参数中传递true即可。

这是对下划线contrib方法的修改,该方法隐式宽松,尝试解析字符串,甚至为isNumeric([1])返回true,这可能是人们真正的陷阱。我上面的方法也会更快,因为它只在parse=true时调用parseFloat()。

我对@CMS的答案唯一的问题是排除了NaN和Infinity,这两个数字在很多情况下都很有用。检查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与另一个优雅的答案非常接近,但它处理十六进制和其他数字的字符串表示。