验证字符串是否为正整数解决方案 1解决方案 2

2022-08-30 00:44:21

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

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


答案 1

两个答案给你:

  • 基于解析

  • 正则表达式

请注意,在这两种情况下,我都将“正整数”解释为包含 ,即使不是正数。我包括笔记,如果你想禁止.000

基于解析

如果希望它是一个规范化的十进制整数字符串,并且值范围合理,可以执行以下操作:

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

它是如何工作的:

  1. 在允许空格和前导零的版本中:
  • str = str.trim();删除任何前导和尾随的白步。
  • if (!str)捕获一个空白字符串并返回,完成其余工作毫无意义。
  • str = str.replace(/^0+/, "") || "0";从字符串中删除所有前导 0,但如果这导致字符串为空,则恢复单个 0。
  1. Number(str):转换为数字;该数字很可能具有小数部分,或者可能是 。strNaN

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

  3. String(...):将结果转换回正常的十进制字符串。对于非常大的数字,这将采用科学记数法,这可能会打破这种方法。(我不太清楚分割在哪里,细节在规格中,但对于整数,我相信它已经超过了21位数字[到那时,数字已经变得非常不精确,因为IEEE-754双精度数字只有大约15位精度。

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

  5. n >= 0:检查它是否为正数。

请注意,对于输入,任何科学记数法中的输入在阶段不会变回相同的科学记数法,并且对于JavaScript使用的那种数字(IEEE-754双精度二进制浮点)的任何值都无法准确表示哪个解析为更接近于给定值的不同值(其中包括超过9,007,199,254,740,992的许多整数);例如, 将失败)。前者很容易解决,后两者则不那么容易。"+1"String(...)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. (...|[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*$

请注意,当您将其转换为数字时:在现代引擎上,使用或执行此操作可能是可以的,但是较旧的引擎可能会以非标准(但以前允许的)方式扩展这些引擎,即前导零表示八进制(基数为8),例如“010”=>8。验证数字后,可以安全地使用它来确保将其解析为十进制(以 10 为基数)。 会忽略字符串末尾的垃圾,但我们已经确保正则表达式没有任何垃圾。+strNumber(str)parseInt(str, 10)parseInt


答案 2

解决方案 1

如果我们认为 JavaScript 整数是最大值(即 ),则以下简短解决方案将完全有效:4294967295Math.pow(2,32)-1

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

描述:

  1. 零填充右移操作员执行三件重要的事情:
    • 截断小数部分
      • 123.45 >>> 0 === 123
    • 负数的偏移
      • -1 >>> 0 === 4294967295
    • “作品”范围MAX_INT
      • 1e10 >>> 0 === 1410065408
      • 1e7 >>> 0 === 10000000
  2. 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_VALUE1.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 % (...)检查值是否为非浮点型 -- 此处(参见 3)的计算方式与 , 和 的情况相同。(...)0false1true

测试:

"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/