Pregunta

Trato de calcular con la función módulo JS', pero no consigo el resultado correcto (que debería ser 1). Aquí es una pieza de código codificado.

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

Result: 66

¿Cuál es el problema aquí?

Saludos, Benedikt

¿Fue útil?

Solución

Un grupo de mejoras a la versión de Benedikt: "Cresta + = '' + cDivident;" es una corrección de errores; parseInt (divisor) hace que sea posible pasar ambos argumentos como cadenas; comprobar la cadena vacía al final hace que siempre devuelven valores numéricos; agregado declaraciones var lo que no está utilizando variables globales; foreach convertido al viejo estilo de lo que funciona en los navegadores con Javascript mayores; fija la cresta == 0; bug (gracias @ 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;
}

Otros consejos

Para un cálculo IBAN formar un número bankaccount normales termino con un número muy grande contenida en un tipo de datos de cadena. De este gran número tengo que encontrar el resto cuando se divide por 97 -. Número> grande 97%

Tan pronto como puedo convertir el tipo de datos a un número entero consigo un desbordamiento que resulta en un número entero negativo y, finalmente, un valor resto mal. Como vi algunas piezas detallados de código (que también dieron resultado malo), no me pude resistir a compartir mi propia. Los créditos van a Búsqueda de módulo de un número muy grande con un número 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. Yo uso 10 posiciones aquí, ya que es más pequeño que los 15 (y algunas) las posiciones de máximo número entero en JavaScript, que se traduce en un número mayor que 97 y es un número redondo. Los dos primeros argumentos son importantes.

Parece que has sido víctima de esto: ¿Qué es el valor entero más alto de JavaScript que un número puede ir a sin perder precisión?

acaba de reiterar lo que está en el otro hilo:

  

son valores de coma flotante de 64 bits, el mayor valor de la integral exacta es 2 ^ 53. Sin embargo, desde la sección de especificaciones [8.5: Tipo Número]:

     

Algunos acuerdo operadores de ECMAScript solamente con números enteros en el rango de -2 ^ 31 a través de 2 ^ 31-1, ambos inclusive, o en el intervalo de 0 a 2 ^ 32-1, inclusive. Estos operadores aceptan cualquier valor del tipo Número pero primero convertir cada tal valor a uno de 2 ^ 32 valores enteros. Ver las descripciones de los operadores ToInt32 y ToUint32 en las secciones 0 y 0, respectivamente

Pero el crédito a quien crédito merece. Jimmy tiene la respuesta aceptada por allí para hacer el trabajo de campo (así, buscando en Google).

Por último, mi solución:

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 aquellos que simplemente quieren copiar y pegar una solución de trabajo (funcional) en ES6 para comprobar 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;}

Incluso podría escribir como una sola línea.

La operación de módulo se realiza en la matriz de enteros que almacenan el número real (divident, aplicado como cadena a la función):

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

Esto funciona porque Modulo es distributiva sobre la suma, resta y multiplicación:

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

La función IBAN transpiled a ES5 se ve así:

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 ha desarrollado un Javascript biblioteca de enteros grandes. Se podría resolver este problema también.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top