javascript - JavaScript验证十进制数字 - isnumeric( )

  显示原文与译文双语对照的内容

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

加分点数:

  1. 清晰。解决方案应该简洁简洁。
  2. Cross-platform 。

测试用例:


 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's 答案非常接近,但在以下情况下它将失败:


//Whitespace strings:
IsNumeric(' ') == true;
IsNumeric('tt') == true;
IsNumeric('nr') == true;

//Number literals:
IsNumeric(-1) == false;
IsNumeric(0) == false;
IsNumeric(1.1) == false;
IsNumeric(8e5) == false;

前一段时间我必须实现一个 IsNumeric 函数,发现如果一个变量包含一个数字值,无论其类型,它可能是一个包含一个数值( 我不得不考虑指数表示法,等等 ) StringNumber 对象,几乎任何事情都有可能被传递给这个函数,我不能做任何类型的假设,照顾类型强制(如。 +true == 1;true 不应该被认为是 "numeric" ) 。

我认为值得分享的这组 +30单元测试众多函数实现,也分享给我所有的测试:


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

更新: 现在是jQuery如何使用( Mid-2014 ) 编辑器:


isNumeric: function( obj ) {
 return!jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1)> = 0;
}

P.S 。isNaN & isFinite混淆行为由于被迫转换为数字。 在ES6中,Number.isNaN & Number.isFinite 将修复这些问题。 在使用它们时记住这点。

Arrrgh 不听正则表达式的答案。 正规表达式 对你来说是不对的,我也不是说性能。 很容易犯微妙的错误,无法用你的正则表达式找出错误。

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


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

下面是它的工作原理:

(input - 0) 表达式强制JavaScript对输入值进行类型强制;它必须首先被解释为减法运算的数字。 如果转换为数字失败,表达式将导致 NaN 。 这数字结果相比,然后你传入的原始值。 由于左边是数字,类型强制再次使用。 既然来自两边的输入被强制为相同的原始值,你应该认为它们总是相同的( 总是真) 。 但是,有一个特殊规则表示 NaN 永远不等于 NaN,因此不能转换为数字( 只有不能转换为数字的值)的值将导致错误。

对长度的检查是针对一个包含空字符串的特殊情况。 还要注意,它在你的0 x89f测试中下降,但这是因为在许多环境中,它是定义一个数字的好方法。 如果你想要捕获特定的场景,你可以添加额外的检查。 更好的是,如果这是你不使用 isNaN()的原因,那么你只需要在 isNaN() 周围包装你自己的函数,就可以进行额外的检查。

总之, 如果你想知道如果一个值可以转换为一个数字,真正开始尝试将它的转换为一个数字。


在进行一些研究之后我又转和用于为什么一个空白字符串没有产生预期的输出,并且我认为我必须马上拥有: 空字符串强制为 0 而不是 NaN 。 只需在长度检查前修剪字符串即可处理这里情况。

仅在一个文检查对如果是numeric,运行单元测试的新代码与它的无限和布尔文字测试时失败,生成代码的唯一情况是应该是一个问题是如果你是( 确切地说,谁会喜欢的类型? 你应该知道 ),并且那将是一些奇怪的代码来生成。

于某种原因,你必须避免相关但还是那句,在任何时候用唯一的原因这是 if.

Yahooui使用:!


isNumber: function(o) {
 return typeof o === 'number' && isFinite(o);
}

这种方式似乎工作得很好:


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') => truen";
 results += (IsNumeric('-1.5')?"Pass":"Fail") +": IsNumeric('-1.5') => truen";
 results += (IsNumeric('0')?"Pass":"Fail") +": IsNumeric('0') => truen";
 results += (IsNumeric('0.42')?"Pass":"Fail") +": IsNumeric('0.42') => truen";
 results += (IsNumeric('.42')?"Pass":"Fail") +": IsNumeric('.42') => truen";
 results += (!IsNumeric('99,999')?"Pass":"Fail") +": IsNumeric('99,999') => falsen";
 results += (!IsNumeric('0x89f')?"Pass":"Fail") +": IsNumeric('0x89f') => falsen";
 results += (!IsNumeric('#abcdef')?"Pass":"Fail") +": IsNumeric('#abcdef') => falsen";
 results += (!IsNumeric('1.2.3')?"Pass":"Fail") +": IsNumeric('1.2.3') => falsen";
 results += (!IsNumeric('')?"Pass":"Fail") +": IsNumeric('') => falsen";
 results += (!IsNumeric('blah')?"Pass":"Fail") +": IsNumeric('blah') => falsen";

 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

是的,内置的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

接受的答案失败了你的测试 #7,我猜这是因为你改变了主意。 这是对接受答案的回应,我有问题。

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

jquery和其他一些javascript库已经包含这样一个函数,通常被称为isnumeric。 还有一个博文在 stackoverflow 上被广泛接受作为答案,上面提到的库的通用例程。


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

首先,上面的代码将 return true 如果参数是一个数组的长度 1,和这一个元素被视为一种数字的上面的逻辑。 在我看来,如果是一个数组,那么它不是数字。

为了缓解这个问题,我添加了一个检查来自逻辑的折扣数组


function isNumber(n) {
 return Object.prototype.toString.call(n)!== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n);
}

当然,你也可以使用 Array.isArray,jquery $.isArray 或者 Prototype 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, ''));
 };
}());

我随即接手所得自组装 +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 = 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("tt"), 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 =/[sS]*return ([sS]*);/.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="http://dl.getdropbox.com/u/35146/js/tests/testrunner.js" type="text/javascript"></script>
<link href="http://dl.getdropbox.com/u/35146/js/tests/testsuite.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">
 <option value="0">
 1.!isNaN(parseFloat(n)) &amp;&amp; isFinite(n)
 </option>

 <option value="1">
 2.!isNaN(n) &amp;&amp;!isNaN(parseFloat(n))
 </option>

 <option value="2">
 3.!isNaN((n))
 </option>

 <option value="3">
 4.!isNaN(parseFloat(n))
 </option>

 <option value="4">
 5. typeof(n)!="boolean" &amp;&amp;!isNaN(n)
 </option>

 <option value="5">
 6. parseFloat(n) === Number(n)
 </option>

 <option value="6">
 7. parseInt(n) === Number(n)
 </option>

 <option value="7">
 8.!isNaN(Number(String(n)))
 </option>

 <option value="8">
 9.!isNaN(+('' + n))
 </option>

 <option value="9">
 10. (+n) == n
 </option>

 <option value="10">
 11. n &amp;&amp;/^-?d+(.d+)?$/.test(n + '')
 </option>

 <option value="11">
 12. isFinite(Number(String(n)))
 </option>

 <option value="12">
 13. isFinite(String(n))
 </option>

 <option value="13">
 14.!isNaN(n) &amp;&amp;!isNaN(parseFloat(n)) &amp;&amp; isFinite(n)
 </option>

 <option value="14">
 15. parseFloat(n) == n
 </option>

 <option value="15">
 16. (n - 0) == n &amp;&amp; n.length &gt; 0
 </option>

 <option value="16">
 17. typeof n === 'number' &amp;&amp; isFinite(n)
 </option>

 <option value="17">
 18.!Array.isArray(n) &amp;&amp;!isNaN(parseFloat(n)) &amp;&amp; isFinite(n.toString().replace(/^-/, ''))
 </option>
 </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>
 </ol>
 </li>

 <li class="pass">
 <strong>Non-Numeric values <b style="color:black;">(0, 18, 18)</b></strong>

 <ol style="display: none;">
 <li class="pass">Empty string: false</li>

 <li class="pass">Whitespace characters string: false</li>

 <li class="pass">Tab characters string: false</li>

 <li class="pass">Alphanumeric character string: false</li>

 <li class="pass">Non-numeric character string: false</li>

 <li class="pass">Boolean true literal: false</li>

 <li class="pass">Boolean false literal: false</li>

 <li class="pass">Number with preceding non-numeric characters: false</li>

 <li class="pass">Number with trailling non-numeric characters: false</li>

 <li class="pass">Undefined value: false</li>

 <li class="pass">Null value: false</li>

 <li class="pass">NaN value: false</li>

 <li class="pass">Infinity primitive: false</li>

 <li class="pass">Positive Infinity: false</li>

 <li class="pass">Negative Infinity: false</li>

 <li class="pass">Date object: false</li>

 <li class="pass">Empty object: false</li>

 <li class="pass">Instance of a function: false</li>
 </ol>
 </li>
</ol>

<div id="main">
 This page contains tests for a set of isNumber functions. To see them, take a look at the source.
</div>

<div>
 <p class="result">Tests completed in 0 milliseconds.
 <br>0 tests of 0 failed.</p>
</div>

自 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 是一个有效的数字( hexa )

...