验证字符串是否为正整数

我想用最简单的故障安全测试来检查JavaScript中的字符串是否是正整数。

isNaN(str)对于所有类型的非整数值返回true,而parseInt(str)对于浮点字符串返回整数,比如"2.5"。我也不想使用一些jQuery插件。

262740 次浏览

看起来正则表达式是可行的:

var isInt = /^\+?\d+$/.test('the string');

给你两个答案:

  • 基于解析

  • < p >正则表达式

注意,在这两种情况下,我都解释为“正整数”;包含0,即使0不是正数。如果你想禁止0,我包含了注释。

基于解析

如果你希望它是一个规范化的十进制整数字符串,在一个合理的值范围内,你可以这样做:

function isInDesiredForm(str) {
var n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0;
}

或者如果你想允许空格和前导零:

function isInDesiredForm(str) {
str = str.trim();
if (!str) {
return false;
}
str = str.replace(/^0+/, "") || "0";
var n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0;
}

实时测试平台(不处理前导零或空白):

function isInDesiredForm(str) {
var n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0;
}
function gid(id) {
return document.getElementById(id);
}
function test(str, expect) {
var result = isInDesiredForm(str);
console.log(
str + ": " +
(result ? "Yes" : "No") +
(expect === undefined ? "" : !!expect === !!result ? " <= OK" : " <= ERROR ***")
);
}
gid("btn").addEventListener(
"click",
function() {
test(gid("text").value);
},
false
);
test("1", true);
test("1.23", false);
test("1234567890123", true);
test("1234567890123.1", false);
test("0123", false); // false because we don't handle leading 0s
test(" 123 ", false); // false because we don't handle whitespace
<label>
String:
<input id="text" type="text" value="">
<label>
<input id="btn" type="button" value="Check">

实时测试平台(处理前导零和空格):

function isInDesiredForm(str) {
str = str.trim();
if (!str) {
return false;
}
str = str.replace(/^0+/, "") || "0";
var n = Math.floor(Number(str));
return String(n) === str && n >= 0;
}
function gid(id) {
return document.getElementById(id);
}
function test(str, expect) {
var result = isInDesiredForm(str);
console.log(
str + ": " +
(result ? "Yes" : "No") +
(expect === undefined ? "" : !!expect === !!result ? " <= OK" : " <= ERROR ***")
);
}
gid("btn").addEventListener(
"click",
function() {
test(gid("text").value);
},
false
);
test("1", true);
test("1.23", false);
test("1234567890123", true);
test("1234567890123.1", false);
test("0123", true);
test(" 123 ", true);
<label>
String:
<input id="text" type="text" value="">
<label>
<input id="btn" type="button" value="Check">

如果你想禁止0,只需将>= 0改为> 0。(或者,在允许前导0的版本中,删除replace行上的|| "0"。)

如何运作:

  1. 在允许空格和前导零的版本中:
  • str = str.trim();删除任何前导和尾随空格。
  • if (!str)捕获一个空字符串并返回,没有必要做其余的工作。
  • str = str.replace(/^0+/, "") || "0";从字符串中删除所有前导0 -但如果结果为空字符串,则恢复单个0。
  1. Number(str):将str转换为数字;这个数字很可能是小数部分,或者可能是NaN

  2. Math.floor:截断数字(截断任何小数部分)。

  3. String(...):将结果转换回正常的十进制字符串。对于非常大的数字,将采用科学计数法,这可能会打破这种方法。(我不太知道分裂在哪里,细节在说明书中,但对于整数,我相信它是在你已经超过21位的点上[此时数字已经变得非常不精确,因为IEEE-754双精度数字只有大约15位精度..)

  4. ... === str:将其与原始字符串进行比较。

  5. n >= 0:检查它是正的。

请注意,这对于输入"+1"无效,任何科学计数法的输入在String(...)阶段不会转换为相同的科学计数法,并且对于JavaScript使用的数字类型(IEEE-754双精度二进制浮点数)的任何值不能准确地表示哪个解析更接近于给定值(其中包括许多超过9,007,199,254,740,992的整数;例如,1234567890123456789将失败)。前者很容易解决,后两者就不那么容易了。

正则表达式

另一种方法是通过正则表达式测试字符串的字符,如果你的目标是只允许(比如说)可选的+后跟0或普通十进制格式的字符串:

function isInDesiredForm(str) {
return /^\+?(0|[1-9]\d*)$/.test(str);
}

生活的实验:

function isInDesiredForm(str) {
return /^\+?(0|[1-9]\d*)$/.test(str);
}
function gid(id) {
return document.getElementById(id);
}
function test(str, expect) {
var result = isInDesiredForm(str);
console.log(
str + ": " +
(result ? "Yes" : "No") +
(expect === undefined ? "" : !!expect === !!result ? " <= OK" : " <= ERROR ***")
);
}
gid("btn").addEventListener(
"click",
function() {
test(gid("text").value);
},
false
);
test("1", true);
test("1.23", false);
test("1234567890123", true);
test("1234567890123.1", false);
test("0123", false); // false because we don't handle leading 0s
test(" 123 ", false); // false because we don't handle whitespace
<label>
String:
<input id="text" type="text" value="">
<label>
<input id="btn" type="button" value="Check">

如何运作:

  1. ^:匹配字符串的开始

  2. \+?:允许一个单独的,可选的+(如果你不想删除它)

  3. (?:...|...):允许以下两个选项之一(不创建捕获组):

  4. (0|...):允许0自己…

  5. < p > (...|[1-9]\d*):…或以0以外的数字开头,后面跟着任何位数的十进制数字。

  6. $:匹配字符串结束。

如果你想不允许0(因为它不是正的),正则表达式就变成了/^\+?[1-9]\d*$/(例如,我们可以失去允许0所需要的替换)。

如果你想允许前导零(0123,00524),那么只需将(?:0|[1-9]\d*)替换为\d+

function isInDesiredForm(str) {
return /^\+?\d+$/.test(str);
}

如果你想允许空格,在^之后添加\s*,在$之前添加\s*

注意:在现代引擎上,使用+strNumber(str)可能会很好,但旧引擎可能会以一种非标准(但以前允许的)方式扩展它们,表示前导零表示八进制(以8为基数),例如“;010"=比;8. 一旦你验证了这个数字,你可以安全地使用parseInt(str, 10)来确保它被解析为十进制(以10为基数)。parseInt将忽略字符串末尾的垃圾,但我们已经确保正则表达式中没有任何垃圾。

return ((parseInt(str, 10).toString() == str) && str.indexOf('-') === -1);

但是,如果您提供'0001'这样的字符串,则无法工作

这几乎是一个重复的问题:

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

答案是:

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

所以,一个正整数是:

function isPositiveInteger(n) {
var floatN = parseFloat(n);
return !isNaN(floatN) && isFinite(n) && floatN > 0
&& floatN % 1 == 0;
}

解决方案1

如果我们考虑一个JavaScript整数为最大值4294967295的值(即Math.pow(2,32)-1),那么下面的简短解决方案将完美工作:

function isPositiveInteger(n) {
return n >>> 0 === parseFloat(n);
}

描述:

  1. 零填充右移位运算符做三件重要的事情:
    • 截断小数部分
      • 123.45 >>> 0 === 123
      • 李< / ul > < / >
      • 对负数进行移位
        • -1 >>> 0 === 4294967295
        • 李< / ul > < / >
        • "works"在MAX_INT范围内
          • 1e10 >>> 0 === 1410065408
          • 1e7 >>> 0 === 10000000
          • 李< / ul > < / > 李< / ul > < / >
          • parseFloat正确解析字符串数字(为非数字字符串设置NaN)

测试:

"0"                     : true
"23"                    : true
"-10"                   : false
"10.30"                 : false
"-40.1"                 : false
"string"                : false
"1234567890"            : true
"129000098131766699.1"  : false
"-1e7"                  : false
"1e7"                   : true
"1e10"                  : false
"1edf"                  : false
" "                     : false
""                      : false

演示: http://jsfiddle.net/5UCy4/37/


解决方案2

另一种方法适用于所有在Number.MAX_VALUE之前有效的数值,即大约1.7976931348623157e+308:

function isPositiveInteger(n) {
return 0 === n % (!isNaN(parseFloat(n)) && 0 <= ~~n);
}

描述:

  1. !isNaN(parseFloat(n))用于过滤字符串值,例如""" ""string";
  2. 0 <= ~~n过滤负的和大的非整数值,例如"-40.1""129000098131766699";
  3. 如果值同时为数字积极的(!isNaN(parseFloat(n)) && 0 <= ~~n)返回true;
  4. 0 === n % (...)检查value是否为非浮点值——这里(...)(见3)在false情况下被计算为0,在true情况下被计算为1

测试:

"0"                     : true
"23"                    : true
"-10"                   : false
"10.30"                 : false
"-40.1"                 : false
"string"                : false
"1234567890"            : true
"129000098131766699.1"  : false
"-1e10"                 : false
"1e10"                  : true
"1edf"                  : false
" "                     : false
""                      : false

演示: http://jsfiddle.net/5UCy4/14/


以前的版本:

function isPositiveInteger(n) {
return n == "0" || ((n | 0) > 0 && n % 1 == 0);
}

演示: http://jsfiddle.net/5UCy4/2/

(~~a == a)其中a是字符串。

我的函数检查数字是否为+ve,也可以是十进制值。

       function validateNumeric(numValue){
var value = parseFloat(numValue);
if (!numValue.toString().match(/^[-]?\d*\.?\d*$/))
return false;
else if (numValue < 0) {
return false;
}
return true;
}

根据上面VisioN的回答,如果你正在使用jQuery验证插件,你可以使用这个:

$(document).ready(function() {
$.validator.addMethod('integer', function(value, element, param) {
return (value >>> 0 === parseFloat(value) && value > 0);
}, 'Please enter a non zero integer value!');
}

然后你可以在你的常规规则集中使用或动态添加它,如下所示:

$("#positiveIntegerField").rules("add", {required:true, integer:true});
如果你正在使用HTML5表单,你可以为表单元素<input type="number" />使用属性min="0"。所有主流浏览器都支持这一功能。它不需要Javascript来完成这些简单的任务,而是集成在新的html标准中。 它被记录在https://www.w3schools.com/tags/att_input_min.asp

在node中工作并跨超过90%的浏览器 (IE和Opera Mini除外)的现代解决方案是使用Number.isInteger,然后进行简单的正检查。

Number.isInteger(x) && x > 0

这是在ECMAScript 2015中完成

function isPositiveInteger(x) {
return Number.isInteger(x) && x > 0
}

Polyfil是:

Number.isInteger = Number.isInteger || function(value) {
return typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value;
};

如果你需要支持可能是字符串数量形式的输入,那么你可以在所有现有的答案(2/1/2018)在某种形式的输入上失败后使用这个函数,我写了一个大型测试套件

function isPositiveInteger(v) {
var i;
return v && (i = parseInt(v)) && i > 0 && (i === v || ''+i === v);
}

简单的

function isInteger(num) {
return (num ^ 0) === num;
}


console.log(isInteger(1));

你也可以扩展Number并通过prototype将函数赋值给它。

ES6:

Number.isInteger(Number(theNumberString)) && Number(theNumberString) > 0

这就是我如何验证一个字符串是一个正整数。

var str = "123";
var str1 = "1.5";
var str2 = "-123";


console.log("is str positive integer: ", Number.isInteger(Number(str)) && Number(str) > 0)
console.log("is str1 positive integer: ", Number.isInteger(Number(str1)) && Number(str1) > 0)
console.log("is str2 positive integer: ", Number.isInteger(Number(str2)) && Number(str2) > 0)

大多数情况下,您需要这种类型的数据库使用检查,如检查字符串是否有效的userId。正因为如此,不可能有任何奇怪的符号可以被分割成整数。此外,整数应该在数据库的整数范围内。你只需要普通的整数,比如1 2 3等等。

const isStrNormPosInt = (str: string) => {
return /^([1-9]\d*)$/.test(str) && Number(str) <= 2147483647 // postgres max int
}

如果检查通过,你可以将它转换为数字Number(str)

我的标准需要在@VisioN的答案上进行一些额外的检查。

  • 不是负数——包括-0
  • 不是小数部分为零的浮点数——0.01.000000
  • 不是指数符号的数字——1e10

我发现这对于验证Express路由器的路由参数很有用。例如/books/:bookId

代码

/**
* Validate that a string is a positive integer
* Excludes float numbers with a zero decimal part, exponential notation and negative 0
* @param n
* @returns {boolean}
*/
function isStrictlyPositiveInteger(n) {
const nString = n.toString(), nInt = parseInt(n), nFloat = parseFloat(n);
// if a negative number (works on -0)
if (nString.charAt(0) === '-') {
return false;
}
// if an exponential like 1e10
if (nString.indexOf('e') > -1) {
return false;
}
// if a float number with a zero decimal part e.g 0.0
if ((nFloat === nInt) && (nString.indexOf('.') > -1)) {
return false;
}
// if a positive integer
// https://stackoverflow.com/a/10835227/8470877
return (0 === n % (!isNaN(nFloat) && 0 <= ~~n));
}

测试

"0"                     : true
"23"                    : true
"-10"                   : false
"10.30"                 : false
"-40.1"                 : false
"string"                : false
"1234567890"            : true
"129000098131766699.1"  : false
"-1e10"                 : false
"1e10"                  : false
"1edf"                  : false
" "                     : false
""                      : false
"0.01"                  : false
"0.00"                  : false
"-0"                    : false
"-0.0"                  : false
"0."                    : false
"-"                     : false
".1"                    : false

我的问题基本上是相同的:检查用户输入的数字是否为整数和正数。

我们的朋友Levi的代码和响应是我迄今为止在整个互联网上发现的最好的,在处理错误方面令人满意。

我在网站上找到了以下代码(https://bobbyhadz.com/blog/javascript-check-if-string-is-positive-integer):

function isPositiveInteger(str) {
if (typeof str !== 'string') {
return false;
}
const num = Number(str);
if (Number.isInteger(num) && num > 0) {
return true;
}
return false;
}

然而,对于1e10,它不能正确返回。