resueltos residuales potencias operacion inversos historia ejercicios ejemplos congruencia clases aritmetica c modulus

residuales - operacion modulo



¿Cuáles son las reglas para la aritmética modular en C? (3)

El operador % se implementa de manera tal que a == b * (a / b) + (a % b) es verdadero, donde usamos la división entera.

En este caso, -111 / 11 es -10 , por lo que -111 == 11 * -10 + x se cumple con x == -1 .

En clases anteriores, me enseñaron que n % d = r y pensar en ello como n = d*q + r , donde d es el divisor, q es el cociente r es el resto (observando que el resto nunca puede ser negativo).

Entonces, por ejemplo, -111 mod 11 es 10 , porque -111 = -11*-11 + 10 (a diferencia de -111 = -11*10 -1 , dado que eso nos daría un resto negativo).

Sin embargo, cuando se imprimen los resultados de -111 % 11 , -1 es el resultado y no 10 . ¿Por qué? ¿No es esto técnicamente incorrecto?


Para módulo, -1 sería una respuesta incorrecta.

Sin embargo, el operador % de C es un operador de resto, no un operador de módulo, y para el resto, se permite 10 o -1.


Respuesta corta:

El estándar garantiza que (a/b)*b + a%b es igual a a .

En C99, el resultado de la división / se truncará hacia cero. El resultado del operador % será seguro, en este caso, -1 .

En C89, el resultado de la división / se puede truncar de cualquier manera para los operandos negativos. Así que el resultado de % operator también depende de la máquina.

Respuesta larga:

Desde C99 6.5.5.

5 El resultado del operador / es el cociente de la división del primer operando por el segundo; El resultado del operador% es el resto. En ambas operaciones, si el valor del segundo operando es cero, el comportamiento no está definido.

6 Cuando los enteros se dividen, el resultado del operador / es el cociente algebraico con cualquier parte fraccionaria descartada. Si el cociente a / b es representable, la expresión (a / b) * b + a% b será igual a a; de lo contrario, el comportamiento de a / b y a% b no está definido.

Y la nota al pie en la misma página para explicar cómo / funciona, dice:

Esto a menudo se llama "truncamiento hacia cero".

De acuerdo con esta regla, -111 / 11 solo puede ser -10 , no 1. Como (a/b)*b + a%b debe ser igual a a , tenemos -111 % 11 es -1 .

Sin embargo, el Capítulo 2.5 de K&R da una respuesta diferente:

La dirección de truncamiento para / y el signo del resultado para% dependen de la máquina para operandos negativos, como lo es la acción realizada en caso de desbordamiento o subdesbordamiento.

De acuerdo con esto, ya sea -1 o 10 puede ser un resultado legal.

La razón está en C89 3.3.5:

Cuando los enteros se dividen y la división es inexacta, si ambos operandos son positivos, el resultado del operador / es el mayor entero menor que el cociente algebraico y el resultado del operador% es positivo. Si cualquiera de los operandos es negativo, si el resultado del operador / es el mayor entero menor que el cociente algebraico o el mayor entero mayor que el cociente algebraico está definido por la implementación, como es el signo del resultado del operador%. Si el cociente a / b es representable, la expresión (a / b) * b + a% b será igual a a.

Resulta ser un cambio de C89 a C99.

La justificación 6.5.5 de C99 proporciona algunas razones históricas:

En C89, la división de enteros con operandos negativos podría redondearse hacia arriba o hacia abajo de una manera definida por la implementación; la intención era evitar incurrir en gastos generales en el código de tiempo de ejecución para verificar casos especiales y hacer cumplir un comportamiento específico. Sin embargo, en Fortran, el resultado siempre se truncará hacia cero, y la sobrecarga parece ser aceptable para la comunidad de programación numérica. Por lo tanto, C99 ahora requiere un comportamiento similar, lo que debería facilitar la transferencia del código de Fortran a C. La tabla en la Sección 7.20.6.2 de este documento ilustra la semántica requerida.

Y aquí está la tabla en §7.20.6.2:

numer denom quot rem 7 3 2 1 –7 3 –2 –1 7 –3 –2 1 –7 –3 2 –1