在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

当前回答

在这里,我从这个页面收集了“好的”,并将它们放入一个简单的测试模式中,供您自行评估。

对于新手来说,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]) );
}

其他回答

它可以在没有RegExp的情况下作为

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

这应该奏效。这里提供的一些功能有缺陷,也应该比这里的任何其他功能都快。

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

解释:

创建自己的副本,然后将数字转换为浮点数,然后将自己与原始数字进行比较,如果它仍然是一个数字(无论是整数还是浮点数),并与原始数字匹配,也就是说,它确实是一个数。

它可以处理数字字符串和普通数字。不适用于十六进制数。

警告:使用风险自负,无保证。

我找到了简单的解决方案,可能不是最好的,但效果很好:)

所以,我接下来要做的是,将字符串解析为Int,并检查新变量的长度大小(现在是Int类型)是否和原始字符串变量的长度相同。从逻辑上讲,如果大小相同,则意味着字符串被完全解析为int,并且只有当字符串仅由数字“构成”时,这才是可能的。

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

您可以很容易地将该代码放在函数中,如果int,则使用return true代替alert。记住,如果您在字符串中使用点或逗号,您将检查它是否仍然为false,因为您正在解析为int。

注意:在e.val上添加1+,因此不会删除起始零。

被接受的答案没有通过你的7号考试,我想这是因为你改变了主意。所以这是对公认答案的回应,我对此有异议。

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

jQuery和其他一些javascript库已经包含了这样一个函数,通常称为isNumeric。在stackoverflow上也有一篇文章被广泛接受作为答案,这与前面提到的库所使用的一般例程相同。

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.isArra,而不是Object.protype.toString.call(n)!=='[object数组]'

我的第二个问题是,负十六进制整数文本字符串(“-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(/^-/, ''));
}

测试解决方案

var testHelper=函数(){var testSuite=函数(){test(“Integer Literals”,函数(){ok(isNumber(“-10”),“负整数字符串”);ok(isNumber(“0”),“零字符串”);ok(isNumber(“5”),“正整数字符串”);ok(isNumber(-16),“负整数”);ok(isNumber(0),“零整数”);ok(isNumber(32),“正整数”);ok(isNumber(“040”),“八进制整数字符串”);ok(isNumber(0144),“八进制整数文字”);ok(isNumber(“-040”),“负八进制整数字符串”);ok(isNumber(-0144),“负八进制整数文字”);ok(isNumber(“0xFF”),“十六进制整数字符串”);ok(isNumber(0xFFF),“十六进制整数文字”);ok(isNumber(“-0xFF”),“负十六进制整数字符串”);ok(isNumber(-0xFFF),“负十六进制整数文字”);});测试(“Foating Point Literals”,函数(){ok(isNumber(“-1.6”),“负浮点字符串”);ok(isNumber(“4.536”),“正浮点字符串”);ok(isNumber(-2.6),“负浮点数”);ok(isNumber(3.1415),“正浮点数”);ok(isNumber(8e5),“指数表示法”);ok(isNumber(“123e-2”),“指数符号字符串”);});测试(“非数值”,函数(){equals(isNumber(“”),false,“空字符串”);equals(isNumber(“”),false,“空白字符串”);equals(isNumber(“\t\t”),false,“制表符字符串”);等于(isNumber(“abcdefghijklm123467890”),false,“字母数字字符串”);等于(isNumber(“xabcdefx”),false,“非数字字符串”);equals(isNumber(true),false,“Boolean true literal”);equals(isNumber(false),false,“Boolean false literal”);等于(isNumber(“bcfed5.2”),false,“前面有非数字字符的数字”);等于(isNumber(“7.2acdgs”),false,“带尾随非数字字符的数字”);equals(isNumber(undefined),false,“未定义值”);equals(isNumber(null),false,“null值”);等于(isNumber(NaN),false,“NaN值”);equals(isNumber(无限),false,“无限基元”);等于(isNumber(Number.POSITIVE_INFINITY),false,“正无穷大”);等于(isNumber(Number.NEGATIVE_INFINITY),false,“负无穷大”);等于(isNumber(新日期(2009,1,1)),false,“日期对象”);equals(isNumber(new Object()),false,“空对象”);equals(isNumber(function(){}),false,“函数的实例”);equals(isNumber([]),false,“空数组”);equals(isNumber([“-10”]),false,“数组负整数字符串”);equals(isNumber([“0”]),false,“Array Zero string”);equals(isNumber([“5”]),false,“数组正整数字符串”);等于(isNumber([-16]),false,“数组负整数”);equals(isNumber([0]),false,“Array Zero integer number”);equals(isNumber([32]),false,“数组正整数”);equals(isNumber([“040”]),false,“数组八进制整数字符串”);equals(isNumber([0144]),false,“数组八进制整数文字”);equals(isNumber([“-040”]),false,“数组负八进制整数字符串”);equals(isNumber([-0144]),false,“数组负八进制整数文字”);equals(isNumber([“0xFF”]),false,“数组十六进制整数字符串”);equals(isNumber([0xFFF]),false,“数组十六进制整数文字”);equals(isNumber([“-0xFF”]),false,“数组负十六进制整数字符串”);等于(isNumber([-0xFFF]),false,“数组负十六进制整数文字”);equals(isNumber([1,2]),false,“具有1个以上正整数的数组”);equals(isNumber([-1,-2]),false,“具有1个以上负整数的数组”);});}var函数ToTest=[函数(n){回来isNaN(parseFloat(n))&&isFinite(n);},函数(n){回来isNaN(n)&&!isNaN(parseFloat(n));},函数(n){回来isNaN((n));},函数(n){回来isNaN(parseFloat(n));},函数(n){返回类型(n)!=“布尔”&&!isNaN(n);},函数(n){return parseFloat(n)==数字(n);},函数(n){return parseInt(n)==数字(n);},函数(n){回来isNaN(数字(字符串(n)));},函数(n){回来isNaN(+(“”+n));},函数(n){返回(+n)==n;},函数(n){返回n&&/^-?\d+(\.\d+)?$/。测试(n+“”);},函数(n){return isFinite(数字(字符串(n)));},函数(n){return isFinite(字符串(n));},函数(n){回来isNaN(n)&&!isNaN(parseFloat(n))&&isFinite(n);},函数(n){返回parseFloat(n)==n;},函数(n){return(n-0)==n&&n长度>0;},函数(n){返回类型n==“number”&&isFinite(n);},函数(n){回来Array.isArray(n)&&!isNaN(parseFloat(n))&&isFinite(n.toString().replace(/^-/,“”));}];//检查函数ToTest数组,提取每个函数的返回语句//并填充toTest select元素。var fillToTestSelect=函数(){对于(var i=0;i<functionsToTest.length;i++){var f=函数ToTest[i].toString();var option=/[\s\s]*return([\s\s]*);/。执行(f)[1];$(“#toTest”).append('<option value=“'+i+'”>'+(i+1)+'.'+option+'</option>');}}var performTest=函数(函数编号){reset();//重置上一测试$(“#tests”).html(“”)//清洁测试结果isNumber=函数ToTest[函数编号];//用要测试的函数重写isNumber全局函数testSuite();//运行测试//获取测试结果var totalFail=0;v

这种方式似乎很有效:

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

要测试它:

常量IsNumeric=(num)=>/^-{0,1}\d*\。{0,1}\d+$/.test(num);函数TestIsNumeric(){var结果=“”results+=(IsNumeric('-1')?“通过”:“失败”)+“:IsNumeric('-1')=>true\n”;结果+=(IsNumeric('-1.5')?“通过”:“失败”)+“:IsNumeric('-1.5')=>true\n”;结果+=(IsNumeric(“0”)?“通过”:“失败”)+“:IsNumeric('0')=>true\n”;结果+=(IsNumeric(“0.42”)?“通过”:“失败”)+“:IsNumeric('0.42')=>true\n”;results+=(IsNumeric('.42')?“通过”:“失败”)+“:IsNumeric('.42')=>true\n”;results+=(!IsNumeric('99999')?“通过”:“失败”)+“:IsNumeric(‘99999’)=>false \n”;results+=(!IsNumeric('0x89f')?“通过”:“失败”)+“:IsNumeric('0x89f')=>false \n”;results+=(!IsNumeric('#abcdef')?“通过”:“失败”)+“:IsNumeric('#abcdef')=>false \n”;results+=(!IsNumeric('1.2.3')?“通过”:“失败”)+“:IsNumeric('1.2.3')=>false \n”;results+=(!IsNumeric(“”)?“通过”:“失败”)+“:IsNumeric(“”)=>false \n”;results+=(!IsNumeric('barh')?“通过”:“失败”)+“:IsNumeric('barh')=>false \n”;返回结果;}console.log(TestIsNumeric());.作为控制台包装{最大高度:100%!重要;顶部: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