Question

J'essaie de calculer avec fonction modulo « JS, mais ne pas le bon résultat (qui devrait être 1). Voici un morceau hardcoded de code.

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

Result: 66

Quel est le problème ici?

Cordialement, Benedikt

Était-ce utile?

La solution

Un tas d'améliorations à la version Benedikt: "CREST + = '' + cDivident;" est un bugfix; parseInt (diviseur) permet de passer les deux arguments sous forme de chaînes; vérifier chaîne vide à la fin la fait revenir toujours des valeurs numériques; ajoutée déclarations var donc il n'utilise pas les variables globales; converti foreach à l'ancien style pour si cela fonctionne dans les navigateurs avec Javascript vieux; fixe la crête == 0; bug (merci @ 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;
}

Autres conseils

Pour un calcul IBAN former un numéro de compte bancaire normale je me retrouve avec un très grand nombre contenu dans un type de chaîne. De ce grand nombre que je dois trouver le reste lorsqu'il est divisé par 97 -.> Grand nombre% 97

Dès que je convertir le type de données à un nombre entier, je reçois un débordement résultant en un nombre entier négatif et finalement une mauvaise valeur de repos. Comme je l'ai vu quelques morceaux de code verbeux (qui a également donné tort résultat), je ne pouvais pas résister à partager mon propre. Crédits vont Trouver Modulus d'un très grand nombre avec un nombre normal

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.. J'utilise 10 positions ici car cela est plus petit que les 15 (et quelques) positions de max entier en JavaScript, il en résulte un nombre plus grand que 97 et il est un beau chiffre rond. Les deux premiers arguments sont importants.

semble que vous ayez été victime à ceci: Quelle est la plus haute valeur entière de JavaScript qu'un nombre peut aller sans perte de précision?

juste pour réitérer ce qui est dans l'autre thread:

  

ce sont des valeurs à virgule flottante de 64 bits, la plus grande valeur de l'intégrale exacte est 2 ^ 53. cependant, de la section de spécification [8.5: Type Numéro]:

     

Certains opérateurs de ECMAScript ne portent que sur des nombres entiers dans la gamme de 31 à -2 ^ 2 ^ 31-1, inclusivement, ou dans la plage de 0 à 2 ^ 32-1, inclusivement. Ces opérateurs acceptent une valeur du type de numéro, mais d'abord convertir chacune de ces valeurs à une de 2 ^ 32 valeurs entières. Voir les descriptions des opérateurs ToInt32 et ToUint32 dans les sections 0 et 0, respectivement

Mais le crédit où le crédit est dû. Jimmy a la réponse acceptée là-bas pour faire le travail sur le terrain (bien, googler).

Enfin, ma solution:

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

Pour ceux qui veulent tout simplement copier et coller une solution de travail (fonctionnelle) dans ES6 pour vérifier les codes 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;}

Vous pouvez même l'écrire comme une doublure.

L'opération modulo est effectuée sur le tableau d'entiers mémoriser le nombre réel (divident, appliqué sous forme de chaîne à fonction):

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

Cela fonctionne parce que Modulo est distributive sur l'addition, la multiplication et soustractions:

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

La fonction IBAN transpiled à ES5 ressemble à:

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

Silencieux Matt a développé une bibliothèque Javascript pour Big Entiers. Il pourrait résoudre ce problème aussi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top