¿Cuál es la diferencia entre "mod" y "resto"?

Resuelto songhir asked hace 11 años • 0 respuestas

Mi amigo dijo que existen diferencias entre "mod" y "resto".

Si es así, ¿cuáles son esas diferencias en C y C++? ¿'%' significa "mod" o "rem" en C?

songhir avatar Dec 03 '12 19:12 songhir
Aceptado

Existe una diferencia entre módulo (división euclidiana) y resto ( %operador de C). Por ejemplo:

-21mod 4es 3porque -21 + 4 x 6es 3.

Pero -21dividido por 4con truncamiento hacia 0(como /operador de C)
da -5un resto (C -21 % 4) de -1.

Para valores positivos, no hay diferencia entre división euclidiana y truncada.

Consulte https://en.wikipedia.org/wiki/Euclidean_division#Other_intervals_for_the_remainder : la elección de C de truncar el resto hacia 0( requerido desde C99 ) fuerza un rango de resto negativo para cocientes negativos. Incluso en C89, cuando el estándar permitía la división euclidiana para/

Si el cociente a/bes representable, la expresión (a/b)*b + a%bserá igual a a.

(-21/4) * 4 + (-21%4) == -21; C99 y posteriores requieren (-5) * 4 + (-1), no euclidianos -6y 3.

David Schwartz avatar Dec 03 '2012 12:12 David Schwartz

¿'%' significa "mod" o "rem" en C?

En C, %es el resto 1 .

..., el resultado del /operador es el cociente algebraico con cualquier parte fraccionaria descartada... (Esto suele denominarse "truncamiento hacia cero"). C11dr §6.5.5 6

Los operandos del %operador serán de tipo entero. C11dr §6.5.5 2

El resultado del /operador es el cociente de la división del primer operando por el segundo; el resultado del %operador es el resto ... C11dr §6.5.5 5


¿Cuál es la diferencia entre "mod" y "resto"?

C no define un operador/función "mod" ni "módulo", como la función de módulo entero utilizada en la división euclidiana u otro módulo .

C define el resto .

Comparemos el "resto" según el %operador con el "mod" euclidiano.

El "mod euclidiano" difiere de la operación de C a%bcuando aes negativo.

 // a % b, the remainder after an integer division that truncates toward 0.
 7 %  3 -->  1  
 7 % -3 -->  1  
-7 %  3 --> -1  
-7 % -3 --> -1   

"Mod" o módulo como en la división euclidiana. El resultado siempre es 0 o positivo.

 7 modulo  3 -->  1
 7 modulo -3 -->  1
-7 modulo  3 -->  2
-7 modulo -3 -->  2

Código de módulo candidato:

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

Nota sobre el punto flotante: double fmod(double x, double y)aunque se llama "fmod", no es lo mismo que la división euclidiana "mod", pero es similar al resto del entero C:

Las fmod funciones calculan el resto de punto flotante de x/y. C11dr §7.12.10.1 2

fmod( 7,  3) -->  1.0
fmod( 7, -3) -->  1.0
fmod(-7,  3) --> -1.0
fmod(-7, -3) --> -1.0

Desambiguación : C también tiene una función con nombre similar double modf(double value, double *iptr)que divide el valor del argumento en partes integrales y fraccionarias, cada una de las cuales tiene el mismo tipo y signo que el argumento. Esto tiene poco que ver con la discusión sobre "mod" aquí, excepto la similitud de nombres.


[Editar diciembre de 2020]

Para aquellos que desean una funcionalidad adecuada en todos los casos, una mejora modulo_Euclidean()que 1) detecta mod(x,0)y 2) un resultado bueno y sin UB con modulo_Euclidean2(INT_MIN, -1). Inspirado en 4 implementaciones diferentes de módulo con comportamiento completamente definido .

int modulo_Euclidean2(int a, int b) {
  if (b == 0) TBD_Code(); // perhaps return -1 to indicate failure?
  if (b == -1) return 0; // This test needed to prevent UB of `INT_MIN % -1`.
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

1 Antes de C99, la definición de C de %todavía era el resto de la división, pero luego /permitía que los cocientes negativos se redondearan hacia abajo en lugar de "truncarlos hacia cero". Consulte ¿Por qué se obtienen valores diferentes para la división de enteros en C89? . Por lo tanto, con alguna compilación anterior a C99, %el código puede actuar como la división euclidiana "mod". Lo anterior modulo_Euclidean()también funcionará con este resto alternativo de la vieja escuela.

chux - Reinstate Monica avatar Dec 17 '2013 15:12 chux - Reinstate Monica

En C y C++ y en muchos lenguajes, %el resto NO es el operador de módulo.

Por ejemplo en la operación -21 / 4la parte entera es -5y la parte decimal es -.25. El resto es la parte fraccionaria multiplicada por el divisor, por lo que nuestro resto es -1. JavaScript utiliza el operador restante y confirma esto

console.log(-21 % 4 == -1);
Expandir fragmento

El operador de módulo es como si tuvieras un "reloj". Imagine un círculo con los valores 0, 1, 2 y 3 en las posiciones de las 12 en punto, 3 en punto, 6 en punto y 9 en punto respectivamente. Al avanzar el cociente en el sentido de las agujas del reloj, obtenemos el resultado de nuestra operación de módulo o, en nuestro ejemplo, con un cociente negativo, en el sentido contrario a las agujas del reloj, lo que da 3.

Nota: El módulo siempre tiene el mismo signo que el divisor y el resto tiene el mismo signo que el cociente. Sumar el divisor y el resto cuando al menos uno es negativo produce el módulo.

theEpsilon avatar Sep 04 '2019 00:09 theEpsilon