Pergunta

Eu tento calcular com função módulo JS', mas não obter o resultado correto (que deve ser 1). Aqui é um pedaço codificado de código.

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

Result: 66

O que é o problema aqui?

Saudações, Benedikt

Foi útil?

Solução

Um grupo de melhorias para a versão de Benedikt: "Crista + = '' + cDivident;" é um bugfix; parseInt (divisor) faz com que seja possível passar ambos os argumentos como cordas; verificar se há string vazia no final faz com que seja sempre retornam valores numéricos; acrescentou declarações var então não é o uso de variáveis ??globais; foreach convertidos para old-estilo para que ele funciona em browsers com Javascript mais velhos; fixo a crista == 0; bugs (graças @ 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;
}

Outras dicas

Para uma forma de cálculo IBAN um número normal bankaccount eu acabar com um número muito grande contido em um tipo de dados string. A partir deste grande número Eu tenho que encontrar o resto quando dividido por 97 -.> Grande número% 97

Assim que eu converter o tipo de dados para um inteiro eu recebo um estouro, resultando em um número inteiro negativo e, eventualmente, um valor restante errado. Como eu vi algumas peças detalhado de código (que também deu resultado errado), eu não pude resistir a compartilhar a minha própria. Os créditos vão para Finding módulo de um número muito grande com uma Normal Número

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

NB. Eu uso 10 posições aqui como este é menor do que os 15 (e algumas) as posições de número inteiro máximo em JavaScript, que resulta em um número maior do que 97 e é um número redondo. Os dois primeiros argumentos importa.

Parece que você caiu vítima a este: O que é mais alto valor inteiro de JavaScript que um número pode ir para sem perder precisão?

apenas para reiterar o que está no outro segmento:

são 64-bit valores de ponto flutuante, o maior valor integral exato é 2 ^ 53. no entanto, a partir da seção de especificação [8.5: Número Type]:

Alguns operadores ECMAScript lidar apenas com números inteiros na faixa -2 ^ 31 a 2 ^ 31-1, inclusive, ou no intervalo de 0 a 2 ^ 32-1, inclusive. Estes operadores aceitar qualquer valor do tipo de número, mas primeiro converter cada valor para tal um de 2 ^ 32 valores inteiros. Veja as descrições dos operadores ToInt32 e ToUint32 em seções 0 e 0, respectivamente

Mas o crédito onde o crédito é devido. Jimmy tem a resposta aceite por lá para fazer o trabalho braçal (bem, pesquisando).

Finalmente, a minha solução:

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

Para aqueles que querem simplesmente copiar e colar uma solução de trabalho (funcional) em ES6 para verificar 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;}

Você mesmo poderia escrevê-lo como um one-liner.

A operação de módulo é realizada na gama de números inteiros que armazenam o número real (divident, aplicado como cadeia de função):

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

Isso funciona porque Modulo é distributivo sobre a adição, subtração e multiplicação:

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

A função IBAN transpiled para ES5 parece com:

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

Silencioso Matt desenvolveu um Javascript biblioteca para inteiros grandes. Ele poderia resolver esta questão também.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top