JavaScript のモジュロ - 大きな数
-
06-09-2019 - |
質問
JS のモジュロ関数を使用して計算しようとしましたが、正しい結果 (1 になるはず) が得られません。これはハードコードされたコードです。
var checkSum = 210501700012345678131468;
alert(checkSum % 97);
Result: 66
ここで何が問題なのでしょうか?
よろしく、ベネディクト
解決
ベネディクトのバージョンの改善の束:「クレスト+ = 『』 + cDivident;」バグ修正です。 parseInt(除数)は、文字列として両方の引数を渡すことが可能になります。最後に空の文字列をチェックすることは、常に数値を返します。これはグローバル変数を使用していないので、VAR文を追加しました。それは、古いJavaScriptを使用してブラウザで動作のための古いスタイルに変換するforeach。 CREST == 0を固定。バグ(Dan.StackOverflow @感謝)。
function modulo (divident, divisor) { var cDivident = ''; var cRest = ''; for (var i in divident ) { var cChar = divident[i]; var cOperator = cRest + '' + cDivident + '' + cChar; if ( cOperator < parseInt(divisor) ) { cDivident += '' + cChar; } else { cRest = cOperator % divisor; if ( cRest == 0 ) { cRest = ''; } cDivident = ''; } } cRest += '' + cDivident; if (cRest == '') { cRest = 0; } return cRest; }
他のヒント
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;
}
N.B。 これはJavaScriptで最大の整数の15(およびいくつかの)位置よりも小さくなっているように私はここで10位を使用し、それが97より大きい数になり、それは素敵なラウンド数です。最初の2つの引数は関係あります。
あなたはこの被害に遭ったようです: Number が精度を失うことなく到達できる JavaScript の最大の整数値は何ですか?
他のスレッドの内容を繰り返すだけです:
これらは 64 ビット浮動小数点値であり、最大の正確な整数値は 2^53 です。ただし、仕様セクション [8.5:数値タイプ]:
一部の ECMAScript 演算子は、-2^31 ~ 2^31-1 の範囲、または 0 ~ 2^32-1 の範囲の整数のみを処理します。これらの演算子は Number 型の任意の値を受け入れますが、最初にそのような各値を 2^32 整数値の 1 つに変換します。ToInt32 演算子と ToUint32 演算子の説明は、それぞれセクション 0 とセクション 0 を参照してください。
しかし、クレジットされるべきところはクレジットします。ジミーは、その下準備を行って (まあ、グーグルで) 受け入れられた答えを向こうで得ました。
最後に、私の解決策ます:
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;
}
ES6 で動作する (機能的な) ソリューションをコピー&ペーストして IBAN を確認したい場合:
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 が加算、減算、乗算に対して分配的であるためです。
- (a+b)%m = ((a%m)+(b%m))%m
- (a-b)%m = ((a%m)-(b%m))%m
- (b)%m = ((a%m)(b%m))%m
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;
};
サイレントマットはビッグ整数のためのJavascript ライブラリを開発しました。それはあまりにも、この問題を解決することができます。