Frage

Ich versuche, mit JS‘Modulo-Funktion zu berechnen, aber nicht bekommen, das richtige Ergebnis (das sollte 1). Hier ist ein Hardcoded Stück Code.

var checkSum = 210501700012345678131468;
alert(checkSum % 97);

Result: 66

Was ist das Problem hier?

Viele Grüße, Benedikt

War es hilfreich?

Lösung

Eine Reihe von Verbesserungen an Benedikt-Version: "CREST + = '' + cDivident;" ist ein bugfix; parseInt (Divisor) macht es möglich, beide Argumente als Strings zu übergeben; Check für leere Zeichenkette am Ende macht es immer numerische Werte zurückgeben; var-Anweisungen hinzugefügt, so es keine globalen Variablen verwendet wird; konvertierte foreach im alten Stil für so funktioniert es in Browsern mit älteren Javascript; die CREST == 0 fixiert ist; Fehler (Dank @ 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;
}

Andere Tipps

Für eine IBAN-Berechnung eine normales Bankkonto Nummer I bilden mit einer sehr großen Zahl in einem String-Datentyp enthalten enden. Aus dieser großen Zahl muß ich den Rest finden, wenn sie durch 97 geteilt. -> große Zahl% 97

Sobald ich den Datentyp in einer ganzen Zahl konvertieren bekomme ich einen Überlauf in einer negativen ganzen Zahl resultierenden und schließlich einen falschen Ruhewert. Als ich einige ausführliche Teile des Codes sah (was auch falsch Ergebnis gab), konnte ich nicht widerstehen mein eigenes zu teilen. Credits geht href="http://www.devx.com/tips/Tip/39012" rel="noreferrer"> Finding Modulus von einer sehr großen Zahl mit einer normalen Anzahl

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. Ich benutze 10 Positionen hier, da dies kleiner als die 15 (und einige) Positionen von max integer in JavaScript, ergibt sich eine Zahl größer als 97 und es ist eine schöne runde Zahl. Die ersten beiden Argumente wichtig sind.

sieht aus wie Sie zum Opfer gefallen diese haben: Was ist höchster integer-Wert des JavaScript, dass eine Nummer gehen kann, ohne Präzision zu verlieren?

nur wiederholen, was in dem anderen Thread:

  

sie sind 64-Bit Fließkommawerte, der größte genaue Integralwert ist 2 ^ 53. jedoch von dem spec Abschnitt [8.5: Anzahl Typ]:

     

Einige ECMAScript Betreiber befassen sich nur mit ganzen Zahlen im Bereich -2 ^ 31 bis 2 ^ 31-1, inklusive, oder im Bereich von 0 bis 2 ^ 32-1, inklusive. Diese Operatoren jeden Wert der Anzahl Typ akzeptieren aber zuerst einem der 2 ^ 32 ganzzahlige Werte, die jeweils einen solchen Wert konvertieren. Siehe die Beschreibungen der ToInt32 und ToUint32 Operatoren in den Abschnitten 0 bzw. 0

Aber Kredit, wem Ehre gebührt. Jimmy bekam die akzeptierte Antwort dort für das Erledigen der Zuarbeit (na ja, googeln).

Schließlich meine Lösung:

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;
}

Für diejenigen, die einfach kopieren möchten und eine Arbeits (funktionale) Lösung in ES6 Paste IBANs zu überprüfen:

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;}

Sie könnten es sogar als Einzeiler schreiben.

die Modulo-Operation auf dem Array von ganzen Zahlen durchgeführt wird, um die tatsächliche Anzahl Speicher (divident, angewandt als String zu funktionieren):

function modulo(divident, divisor){
   return Array.from(divident).map(c => parseInt(c)).reduce((remainder, value) => (remainder * 10 + value) % divisor,0);
};

Das funktioniert, weil Modulo ist distributive über Addition, Subtraktion und Multiplikation:

  • (a + b)% m = ((a% m) + (b% m))% m
  • (a-b)% m = ((a% m) - (b% m))% m
  • (a b)% m = ((a% m) (b% m))% m

Die IBAN Funktion transpiled zu ES5 wie folgt aussieht:

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;
};

Stille Matt hat eine Javascript Bibliothek für Big Integers entwickelt. Es könnte auch dieses Problem lösen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top