
Alba
En un programa C, estaba probando las siguientes operaciones (solo para verificar el comportamiento)
x = 5 % (-3);
y = (-5) % (3);
z = (-5) % (-3);
printf("%d ,%d ,%d", x, y, z);
Me dio salida como (2, -2 , -2)
en gcc. Esperaba un resultado positivo cada vez. ¿Puede un módulo ser negativo? ¿Alguien puede explicar este comportamiento?

ouah
Él %
El operador en C no es el módulo operador pero el recordatorio operador.
Los operadores de módulo y resto difieren con respecto a los valores negativos.
Con un operador de resto, el signo del resultado es el mismo que el del dividendo (numerador), mientras que con un operador de módulo el signo del resultado es el mismo que el del divisor (denominador).
C define el %
operación para a % b
como:
a == (a / b * b) + a % b
con /
la división entera con truncamiento hacia 0
. Ese es el truncamiento que se hace hacia 0
(y no hacia el infinito negativo) que define el %
como un operador de resto en lugar de un operador de módulo.

ArjunShankar
C99 requiere que cuando a/b
es representable:
(a/b) * b
+ a%b
será igual a
Esto tiene sentido, lógicamente. ¿Derecha?
Veamos a qué conduce esto:
Ejemplo A. 5/(-3)
es -1
=> (-1) * (-3)
+ 5%(-3)
= 5
Esto solo puede suceder si 5%(-3)
es 2
Ejemplo B. (-5)/3
es -1
=> (-1) * 3
+ (-5)%3
= -5
Esto solo puede suceder si (-5)%3
es -2

dewang
Basado en la especificación C99: a == (a / b) * b + a % b
Podemos escribir una función para calcular (a % b) == a - (a / b) * b
!
int remainder(int a, int b)
{
return a - (a / b) * b;
}
Para la operación de módulo, podemos tener la siguiente función (asumiendo b > 0
)
int mod(int a, int b)
{
int r = a % b;
return r < 0 ? r + b : r;
}
mi conclusión es que a % b
en C es una operación de resto y NO una operación de módulo.

Udayraj Deshmukh
No creo que haya necesidad de verificar si el número es negativo.
Una función simple para encontrar el módulo positivo sería esta:
Editar: Asumiendo N > 0
y N + N - 1 <= INT_MAX
int modulo(int x,int N){
return (x % N + N) %N;
}
Esto funcionará para tanto positivo como negativo valores de x.
PD original: también como lo señaló @chux, si su x y N pueden alcanzar algo como INT_MAX-1 e INT_MAX respectivamente, simplemente reemplace int
con long long int
.
Y si también cruzan los límites de long long (es decir, cerca de LLONG_MAX), entonces deberá manejar los casos positivos y negativos por separado como se describe en otras respuestas aquí.
De acuerdo a estándar C99sección 6.5.5 Operadores multiplicativosse requiere lo siguiente:
(a / b) * b + a % b = a
Conclusión
El signo del resultado de una operación de resto, según C99, es el mismo que el del dividendo.
Veamos algunos ejemplos (dividend / divisor
):
Cuando solo el dividendo es negativo
(-3 / 2) * 2 + -3 % 2 = -3
(-3 / 2) * 2 = -2
(-3 % 2) must be -1
Cuando solo el divisor es negativo
(3 / -2) * -2 + 3 % -2 = 3
(3 / -2) * -2 = 2
(3 % -2) must be 1
Cuando tanto el divisor como el dividendo son negativos
(-3 / -2) * -2 + -3 % -2 = -3
(-3 / -2) * -2 = -2
(-3 % -2) must be -1
6.5.5 Operadores multiplicativos
Sintaxis
- expresión-multiplicativa:
cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression
Restricciones
- Cada uno de los operandos tendrá tipo aritmético. Los operandos de la % El operador debe tener un tipo entero.
Semántica
-
Las conversiones aritméticas habituales se realizan en los operandos.
-
El resultado del binario. * El operador es el producto de los operandos.
-
el resultado de la / operador es el cociente de la división del primer operando por el segundo; el resultado de la % el operador es el resto. En ambas operaciones, si el valor del segundo operando es cero, el comportamiento es indefinido.
-
Cuando se dividen números enteros, el resultado de la / operador es el cociente algebraico con cualquier parte fraccionaria descartada [1]. Si el cociente a/b
es representable, la expresión (a/b)*b + a%b
será igual a
.
[1]: Esto a menudo se denomina “truncamiento hacia cero”.
¿Puede un módulo ser negativo?
%
puede ser negativo ya que es el operador resto, el resto después de la división, no después División_euclidiana. Desde C99 el resultado puede ser 0, negativo o positivo.
// a % b
7 % 3 --> 1
7 % -3 --> 1
-7 % 3 --> -1
-7 % -3 --> -1
Él módulo OP buscado es un clasico módulo euclidianono %
.
Esperaba un resultado positivo cada vez.
Para realizar un módulo euclidiano que esté bien definido siempre que a/b
se define, a,b
son de cualquier signo y el resultado nunca es negativo:
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;
}
modulo_Euclidean( 7, 3) --> 1
modulo_Euclidean( 7, -3) --> 1
modulo_Euclidean(-7, 3) --> 2
modulo_Euclidean(-7, -3) --> 2

yuhao
Las otras respuestas han explicado en C99 o posterior, la división de números enteros que involucran operandos negativos siempre truncar hacia cero.
Tenga en cuenta que, en C89, si el redondeo del resultado hacia arriba o hacia abajo está definido por la implementación. Porque (a/b) * b + a%b
es igual a
en todos los estándares, el resultado de %
la participación de operandos negativos también está definida por la implementación en C89.
Posible duplicado de stackoverflow.com/questions/4003232/…
– James
30 de julio de 2012 a las 11:41
posible duplicado del operador Modulo con valores negativos
– sugavaneshb
8 de febrero de 2015 a las 8:46
Hay dos interpretaciones diferentes del módulo. torstencurdt.com/tech/posts/modulo-of-negative-numbers
– tcurdt
1 de febrero a las 12:26