验证 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

答案

@Joel 的答案非常接近,但在以下情况下将失败:

// 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 isNaNisFinite的行为令人困惑。在 ES6 中, Number.isNaNNumber.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));
}

啊!不要听正则表达式的答案。正则表达式对此很讨厌,我不只是在谈论性能。使用正则表达式可以轻松,轻松地发现错误非常容易。

如果您不能使用isNaN() ,这应该会更好:

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

运作方式如下:

(input - 0)表达式强制 JavaScript 对您的输入值进行强制类型转换;首先必须将其解释为减法运算的数字。如果该转换为数字失败,则表达式将得出NaN 。然后将此数字结果与您传入的原始值进行比较。由于左侧现在是数字,因此再次使用强制类型。现在,将来自双方的输入从相同的原始值强制转换为相同的类型,您将认为它们应该始终相同(始终为 true)。但是,有一条特殊的规则说NaN永远不等于NaN ,因此不能转换为数字的值(只有不能转换为数字的值)将导致错误。

长度检查是针对涉及空字符串的特殊情况。另请注意,它取决于您的 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

雅虎! UI使用此:

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

这也适用于 0x23 类型编号。

接受的答案未通过您的#7 测试,我想这是因为您改变了主意。因此,这是对我遇到的问题的答复。

在某些项目中,我需要验证一些数据,并尽可能确定它是可以在数学运算中使用的 javascript 数值。

jQuery 和其他一些 JavaScript 库已经包含了这样的函数,通常称为isNumeric关于堆栈溢出文章也已被广泛接受为答案,与上述库所使用的一般例程相同。

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

首先,如果参数是一个长度为 1 的数组,并且上面的逻辑将该单个元素的类型视为数字,则上面的代码将返回 true。我认为,如果它是一个数组,那么它不是数字。

为了缓解此问题,我从逻辑上对折扣数组添加了检查

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

然后,我接受了 CMS + 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(/^-/, ''));
}

是的,内置的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是有效数字(六)

无需 RegExp 即可完成,因为

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