JS の modulo 関数で計算しようとしましたが、正しい結果が得られません (1 になるはずです)。これはハードコードされたコードです。
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
ここで何が問題なのですか?
よろしく、 ベネディクト
JS の modulo 関数で計算しようとしましたが、正しい結果が得られません (1 になるはずです)。これはハードコードされたコードです。
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
ここで何が問題なのですか?
よろしく、 ベネディクト
IBAN 計算フォームの通常の銀行口座番号の場合、文字列データ型に含まれる非常に大きな数値になります。この大きな数から、97 で割ったときの残りを見つけなければなりません -> 大きな数 % 97.
データ型を整数に変換するとすぐにオーバーフローが発生し、負の整数になり、最終的に残りの値が間違ってしまいます。いくつかの冗長なコード (これも間違った結果をもたらした) を見たので、私は自分自身を共有することに抵抗できませんでした。クレジットは、正規数で非常に大きな数のモジュラスを見つけるに行きます
modulo: function(divident, divisor) {
var partLength = 10;
while (divident.length > partLength) {
var part = divident.substring(0, partLength);
divident = (part % divisor) + divident.substring(partLength);
}
return divident % divisor;
}
注意: ここでは 10 桁を使用します。これは、JavaScript の最大整数の 15 桁 (および一部) よりも小さいため、97 よりも大きな数値になり、適切な丸め数です。最初の 2 つの引数が重要です。
Benedikt のバージョンに対する一連の改善: "cRest += '' + cDivident;" バグ修正です。parseInt(divisor) を使用すると、両方の引数を文字列として渡すことができます。最後に空の文字列をチェックすると、常に数値が返されます。グローバル変数を使用しないように var ステートメントを追加しました。foreach を古いスタイルの for に変換したため、古い Javascript を使用するブラウザーで動作します。cRest == 0; を修正しました。バグ(@Dan.StackOverflowに感謝)。
function modulo (除数、除数) {
var cDivident = '';
var cRest = '';
for (被除数の変数 i ) {
var cChar = 被除数[i];
var cOperator = cRest + '' + cDivident + '' + cChar;
if (cOperator < parseInt(divisor) ) {
cDivident += '' + cChar;
} そうしないと {
cRest = cOperator % 除数;
もし ( cRest == 0 ) {
cRest = '';
}
cDivident = '';
}
}
cRest += '' + cDivident;
もし (cRest == '') {
cRest = 0;
}
cRestを返します。
}
あなたはこれの犠牲になっているように見えます:数値が精度を失うことなく行くことができるJavaScriptの最大の整数値は何ですか?
他のスレッドの内容を繰り返すだけです。
これらは64ビット浮動小数点値であり、最大の正確な整数値は2^53です。ただし、仕様セクション[8.5:数値タイプ]から:
一部のECMAScript演算子は、-2^31から2^31-1までの範囲、または0から2^32-1までの範囲の整数のみを処理します。これらの演算子はNumber型の任意の値を受け入れますが、最初にそのような各値を2^32整数値の1つに変換します。それぞれセクション0および0のToInt32およびToUint32演算子の説明を参照してください。
しかし、クレジットが必要な場合はクレジットします。ジミーは、レッグワーク(まあ、グーグル)をしたことで、あちらで受け入れられた答えを得ました。
IBAN を確認するために ES6 で動作する (機能する) ソリューションをコピー&ペーストするだけの場合:
function isIBAN(s){
const rearranged = s.substring(4,s.length) + s.substring(0,4);
const numeric = Array.from(rearranged).map(c =>(isNaN(parseInt(c)) ? (c.charCodeAt(0)-55).toString() : c)).join('');
const remainder = Array.from(numeric).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % 97,0);
return remainder === 1;}
ワンライナーで書くこともできます。
モジュロ演算は、実際の数値を格納する整数の配列に対して実行されます (dividentは、文字列として関数に適用されます)。
function modulo(divident, divisor){
return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};
これが機能するのは、Modulo が加算、減算、乗算に対して分配的であるためです。
ES5 にトランスパイルされた IBAN 関数は次のようになります。
function (s) {
var rearranged = s.substring(4, s.length) + s.substring(0, 4);
var numeric = Array.from(rearranged).map(function (c) { return (isNaN(parseInt(c)) ? (c.charCodeAt(0) - 55).toString() : c); }).join('');
var remainder = Array.from(numeric).map(function (c) { return parseInt(c); }).reduce(function (remainder, value) { return (remainder * 10 + value) % 97; }, 0);
return remainder === 1;
};
最後に、私の解決策:
function modulo (divident, divisor) {
cDivident = '';
cRest = '';
for each ( var cChar in divident ) {
cOperator = cRest + '' + cDivident + '' + cChar;
if ( cOperator < divisor ) {
cDivident += '' + cChar;
} else {
cRest = cOperator % divisor;
if ( cRest == 0 ) cRest = '';
cDivident = '';
}
}
return cRest;
}
Silent Matt はBig Integers 用の Javascriptライブラリを開発しました。この問題も解決できます。