2012-07-30 63 views
115

En un programa C que estaba tratando las operaciones siguientes (sólo para comprobar el comportamiento)operación de módulo con números negativos

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 todo el tiempo. ¿Puede un módulo ser negativo? ¿Alguien puede explicar este comportamiento?

+0

Posible duplicado de http://stackoverflow.com/questions/4003232/how-to-code-a-modulo-operator-in-cc-obj-c-that-handles-negative-numbers – james

+1

posible duplicado de [ Operador de módulo con valores negativos] (http://stackoverflow.com/questions/7594508/modulo-operator-with-negative-values) – sugavaneshb

Respuesta

3

El resultado de la operación módulo depende del signo del numerador, y por lo tanto de que está recibiendo -2 para y y z

Aquí está la referencia

http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_14.html

Entero División

Esta sección describe las funciones para realizar la división de enteros. Estas funciones son redundantes en la biblioteca GNU C, ya que en GNU C el operador '/' siempre se redondea hacia cero. Pero en otras implementaciones de C , '/' puede redondear de manera diferente con argumentos negativos. div y ldiv son útiles porque especifican cómo redondear el cociente : hacia cero. El resto tiene el mismo signo que el numerador .

+4

Se refiere a un texto sobre ANSI C. Esta es una norma bastante antigua de C. No Asegúrese de que el texto sea correcto con respecto a ANSI C, pero definitivamente no con respecto a C99. En C99 §6.5.5 la división entera se define para siempre truncar hacia cero. – Palec

+0

y un enlace: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf –

102

C99 requiere que cuando a/b es representable:

(a/b) * b+a%b será igual a

Esto tiene sentido, como es lógico. ¿Correcto?

Veamos lo que esto conduce a:


Ejemplo A. 5/(-3) es -1

=>(-1) * (-3)+5%(-3) = 5

Esto sólo puede ocurrir si 5%(-3) es 2.


Ejemplo B.(-5)/3 es -1

=>(-1) * 3+(-5)%3 = -5

Esto sólo puede ocurrir si (-5)%3 es -2

+1

¿El compilador debe ser lo suficientemente inteligente y detectar que un módulo sin firmar y otro no firmado siempre es positivo? Actualmente (bueno, GCC 5.2) el compilador parece pensar que "%" devuelve un "int" en este caso, en lugar de "unsigned" incluso cuando ambos operandos son uint32_t o más grandes. –

+0

@FrederickNord ¿Tiene un ejemplo para mostrar [ese comportamiento] (http://stackoverflow.com/questions/11720656/modulo-operation-with-negative-numbers#comment66655578_11720841)? – chux

85

El operador % en C no es el operador módulo pero el resto 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 signo del dividendo, mientras que con un operador de módulo el signo del resultado es el mismo que el del divisor.

C define la operación % para a % b como:

a == (a/b * b) + a % b 

con / la división de número entero con truncamiento hacia 0. Ese es el truncamiento que se hace hacia 0 (y no hacia la infinitud negativa) que define el % como un operador de resto en lugar de un operador de módulo.

+4

[El resto es el resultado de la operación del módulo] (https://en.wikipedia.org/wiki/Remainder) por definición. No debería haber nada como el operador de resto porque no existe el resto de la operación, se llama modulo. – gronostaj

+21

@gronostaj no en CS. Observe los lenguajes de nivel superior como Haskell o Scheme que definen dos operadores diferentes ('restoder' y' modulo' en Scheme, 'rem' y' mod' en Haskell). Estas especificaciones de los operadores difieren en estos idiomas sobre cómo se realiza la división: truncamiento hacia 0 o hacia el infinito negativo. Por cierto, el estándar C nunca llama al operador '%' the * modulo *, simplemente lo llaman el * operador% *. – ouah

+0

No debe confundirse con la función _ resto_del_C, que implementa el resto IEEE con semántica de redondeo hacia el más cercano en la división – Eric

44

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 operación de módulo, que puede tener la función siguiente (suponiendo que b> 0)

int mod(int a, int b) 
{ 
    int r = a % b; 
    return r < 0 ? r + b : r; 
} 

Mi conclusión es (a% b) en C es un operador de resto y NO modulo operador.

+1

Esto no da resultados positivos cuando 'b' es negativo (y de hecho para' r' y 'b' ambos negativos da resultados menores que' -b'). Para garantizar resultados positivos para todas las entradas, puede usar 'r + abs (b)' o para hacer coincidir el signo 'b's, en su lugar podría cambiar la condición a' r * b <0'. –

4

Las otras respuestas han explicado en C99 o temprano, la división de números enteros negativos que implican operandos siempre truncar a cero.

Tenga en cuenta que, en C89, si el resultado redondeado hacia arriba o hacia abajo está definido por la implementación. Como (a/b) * b + a%b es igual a a en todos los estándares, el resultado de % que implica operandos negativos también se define en la implementación en C89.

23

No creo que haya ninguna necesidad de verificar si el número es negativo. La función general más simple para encontrar el módulo positivo sería esta - Funcionaría tanto en valores positivos como negativos de x.

int modulo(int x,int N){ 
    return (x % N + N) %N; 
} 
+0

Esto funcionó para mí. ¡¡¡Gracias!!! –

3

En Matemáticas, de donde surgen estas convenciones, no hay ninguna afirmación de que la aritmética de módulo debería arrojar un resultado positivo.

Por ejemplo.

1 mod 5 = 1, pero también puede ser igual a -4.Es decir, 1/5 produce un resto 1 de 0 o -4 de 5. (Ambos factores de 5)

De manera similar, -1 mod 5 = -1, pero también puede ser igual a 4. Esto es, - 1/5 produce un resto -1 de 0 o 4 de -5. (Ambos factores de 5)

Para obtener más información, consulte equivalence classes en Matemáticas.

0

El operador de módulo es como el operador de mod cuando el número es positivo, pero diferente si el número es negativo.

Muchas veces en los problemas se nos pide que demos la respuesta modulo 10^9 + 7.

Deje que la respuesta (antes de usar el módulo) se denote por 'a'.

simple Sencillo REGLA

si a es positivo, a continuación, un módulo 10^9 + 7 = un% (10^9 + 7)

si a es negativo, a continuación, un módulo 10^9 + 7 = (un% (10^9 + 7)) + (10^9 + 7)

Si, en suc h problemas, encontramos que cualquier paso del ciclo puede calcular un valor que está fuera del rango entero (si estamos usando números enteros), entonces podemos usar el operador de módulo en ese paso en sí mismo. La respuesta final será como si hubiéramos usado el operador de módulo solo una vez.

Esto es porque- (a * b)% c = ((a% c) (b% c))% c Lo mismo ocurre con la suma y la resta.

1

El operador del módulo proporciona el resto. operador de módulo en C por lo general toma la señal de la numerador

  1. x = 5% (-3) - aquí numerador es positiva por lo tanto resulta en 2
  2. y = (-5)% (3) - aquí numerador es negativo, por lo tanto resulta -2
  3. z = (-5)% (-3) - aquí numerador es negativo, por lo tanto resulta -2

también módulo (resto) operador sólo se puede utilizar con tipo entero y no se puede usar con coma flotante.

+0

Sería bueno si puedes respaldar esto con enlaces a recursos externos. –

+0

https://archive.org/details/letusc_201605 – Kavya

Cuestiones relacionadas