1. ホーム
  2. ジャバスクリプト

[解決済み】文字列が正整数であることを検証する

2022-04-16 12:27:42

質問

JavaScriptの文字列が正の整数であることをチェックするための最も簡単なフェールセーフテストが欲しい。

isNaN(str) はあらゆる種類の非整数の値に対して真を返し parseInt(str) は "2.5" のような浮動小数点文字列に対して整数を返しています。また、jQueryのプラグインを使うのも嫌です。

解決方法は?

2つの答えを用意しました。

  • 構文解析に基づく

  • 正規表現

どちらの場合も、quot;正の整数を含むと解釈していることに注意してください。 0 であるにもかかわらず 0 は正でない。を不許可にする場合は注意書きを入れています。 0 .

構文解析に基づく

合理的な値の範囲で正規化された10進整数文字列にしたい場合は、このようにします。

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 つだけ復元する。
  1. Number(str) : 変換 str を数値に変換します。数値は小数の部分を持つこともありますし、あるいは NaN .

  2. Math.floor : 数値を切り捨てる(端数部分を切り落とす)。

  3. String(...) : 結果を通常の10進文字列に変換し直します。本当に大きな数字の場合は、科学的記数法になるので、この方法は破綻する可能性がある。(どこで分岐しているのかよくわからない。 詳細は仕様書に記載されています。 しかし、整数の場合は、21桁を超えたあたりからだと思います(IEEE-754の倍精度の数値は15桁程度の精度しかないので、この時点で数値は非常に不正確になっています...)。

  4. ... === str : 元の文字列と比較します。

  5. n >= 0 : 正であることを確認する。

に対して失敗することに注意してください。 "+1" で同じ科学的記法に戻らない科学的記法の入力は、すべて String(...) また、JavaScript が使用する数値の種類 (IEEE-754 倍精度バイナリ浮動小数点) が正確に表現できず、与えられた値よりも異なる値に近いと解析される値 (9,007,199,254,740,992 以上の多くの整数を含む。例) に対してもです。 1234567890123456789 は失敗します)。前者は簡単に修正できますが、後者2つはそうでもありません。

正規表現

もうひとつの方法は、正規表現を使って文字列の文字をテストすることです。 + のどちらかが続きます。 0 または通常の10進数形式の文字列を指定します。

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. (?:...|...) : この2つのオプションのうち1つを許可する(キャプチャグループを作成しない)。

  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* 直前 $ .

これを数値に変換するときの注意点。現代のエンジンでは、おそらく +str または Number(str) しかし、古いものでは、標準的でない (しかし以前は許されていた) 方法でそれらを拡張し、先頭のゼロは、次のように意味すると言っている場合があります。 8進数 (ベース8)のように、例えば "010" => 8 のような数字です。 parseInt(str, 10) を使えば、10進数としてパースされるようになります。 parseInt は文字列の末尾にあるゴミを無視しますが、正規表現でゴミがないことを確認しています。