2010-10-07 21 views
39

he encontrado un comportamiento extraño en Python con respecto a los números negativos:La operación de módulo en números negativos en Python

>>> a = -5 
>>> a % 4 
3 

Podría alguien explicar lo que está pasando?

+14

me parece bien – wheaties

+3

'..., -9, -5, -1, 3, 7, ...' – NullUserException

+0

posible duplicado de [C, Python - comportamiento diferente de la operación del módulo (%)] (http://stackoverflow.com/questions/1907565/c-python-different-behaviour-of-the-modulo-operation) – nyuszika7h

Respuesta

68

A diferencia de C o C++, el operador de módulo de Python (%) siempre devuelve un número que tiene el mismo signo que el denominador (divisor). Sus rendimientos de expresión 3 porque

(-5)% 4 = (-2 × 4 + 3)% 4 = 3.

Se elige sobre el comportamiento C porque un resultado negativo es a menudo más útil. Un ejemplo es calcular los días de la semana. Si hoy es martes (día # 2), ¿cuál es el día de la semana N días antes? En Python podemos calcular con

return (2 - N) % 7 

pero en C, si N ≥ 3, obtenemos un número negativo que es un número no válido, y tenemos que fijar manualmente mediante la adición de 7:

int result = (2 - N) % 7; 
return result < 0 ? result + 7 : result; 

(Ver http://en.wikipedia.org/wiki/Modulo_operator de cómo se determina el signo del resultado para diferentes idiomas.)

+1

¿No debería ser eso (-2 * 4 + 3)? – Vatine

+0

@Vatine: Corregido gracias. (Estaba pensando en 5 ^^) – kennytm

+0

¿Cómo se emula a este operador tan útil en C/C++? –

2

Modulo, clases de equivalencia para 4:

  • 0: 0, 4, 8, 12 ... y -4, -8, -12 ...
  • 1: 1, 5, 9, 13 ... y -3, -7, -11 ...
  • 2: 2, 6, 10 ... y -2, -6, -10 ...
  • 3: 3, 7, 11 ... y -1, -5, -9 ...

Aquí hay un enlace al modulo's behavior with negative numbers. (Sí, lo busqué en Google)

+0

@NullUserException - sí, lo era. fijo. Gracias. – wheaties

7

No hay una mejor manera de manejar divisiones enteras y modificaciones con números negativos. Sería bueno si a/b fuera de la misma magnitud y el signo opuesto de (-a)/b. Sería bueno si a % b fuera de hecho un módulo b. Como realmente queremos a == (a/b)*b + a%b, los primeros dos son incompatibles.

Cuál mantener es una pregunta difícil, y hay argumentos para ambas partes. C y C++ división entera redonda hacia cero (por lo que a/b == -((-a)/b)), y aparentemente Python no lo hace.

2

Como se señaló, el módulo de Python hace una excepción well-reasoned a las convenciones de otros idiomas. Esto le da a los números negativos un comportamiento perfecto, especialmente cuando se usa en combinación con el operador de división de enteros //, como suele ser el módulo % (como en matemáticas).divmod):

for n in range(-8,8): 
    print n, n//4, n%4 

Produce:

-8 -2 0 
-7 -2 1 
-6 -2 2 
-5 -2 3 

-4 -1 0 
-3 -1 1 
-2 -1 2 
-1 -1 3 

    0 0 0 
    1 0 1 
    2 0 2 
    3 0 3 

    4 1 0 
    5 1 1 
    6 1 2 
    7 1 3 
+0

Gracias su ejemplo me hizo entenderlo :) – Lamis

1

También piensan que el comportamiento extraño de Python. Resulta que no estaba resolviendo bien la división (en papel); Estaba dando un valor de 0 al cociente y un valor de -5 al resto. Terrible ... Olvidé la representación geométrica de los números enteros. Al recordar la geometría de los números enteros proporcionados por la recta numérica, uno puede obtener los valores correctos para el cociente y el resto, y verificar que el comportamiento de Python sea correcto. (Aunque supongo que ya ha resuelto su problema hace mucho tiempo).

Cuestiones relacionadas