¿Cómo funciona el operador de módulo (%) en números negativos en Python?

2 minutos de lectura

avatar de usuario de facha
facha

Exactamente como funciona el % trabajo del operador en Python, particularmente cuando se trata de números negativos?

Por ejemplo, ¿por qué -5 % 4 evaluar a 3en lugar de, digamos, -1?

  • me parece bien

    – trigo

    7 oct 2010 a las 15:04

  • ..., -9, -5, -1, 3, 7, ...

    – NullUserException

    7 oct 2010 a las 15:19


  • posible duplicado de C, Python: comportamiento diferente de la operación de módulo (%)

    – alexia

    17 de julio de 2014 a las 8:56

  • Puedes usar math.fmod para obtener el mismo comportamiento que en C o Java.

    – 0x2b3bfa0

    28 de enero de 2017 a las 16:42

avatar de usuario de kennytm
kennytm

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). Tu expresión da 3 porque

(-5) / 4 = -1,25 –> suelo(-1,25) = -2

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

Se elige sobre el comportamiento C porque un resultado no negativo suele ser 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? norte ¿días antes? En Python podemos calcular con

return (2 - N) % 7

pero en C, si norte ≥ 3, obtenemos un número negativo que no es válido y debemos corregirlo manualmente agregando 7:

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

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

  • Sorprendentemente, el operador de módulo de Python (%) no es siempre devolver un número que tenga el mismo signo que el denominador (divisor). Ver stackoverflow.com/questions/48347515/…

    – zezollo

    19 de enero de 2018 a las 18:36


  • @zezollo tu comentario se aplica a Decimal objetos pero no a enteros ordinarios, ¿verdad?

    – kuzzooroo

    10 de enero a las 13:04

  • @kuzzooroo sí, el comportamiento es diferente entre Decimal y int objetos, como puede ver en el enlace a la pregunta.

    – zezollo

    hace 18 horas

Aquí hay una explicación de Guido van Rossum:

http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html

Esencialmente, es así que a/b = q con resto r preserva las relaciones b*q + r = a y 0

  • Los lenguajes como C ++ y Java también conservan la primera relación, pero ceil por negativa apositivo b, mientras que los suelos de Python. siempre es cierto que abs(r) < by ceil iff r <= 0.

    –Evgeni Sergeev

    22 de abril de 2014 a las 7:43


Avatar de usuario de Munkhbold Enkhtur
Munkhbold Enkhtur

En pitónel operador de módulo funciona así.

>>> mod = n - math.floor(n/base) * base

por lo que el resultado es (para su caso):

mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3

Mientras que otros idiomas como C, JAVA, JavaScript use truncamiento en lugar de piso.

>>> mod = n - int(n/base) * base

lo que resulta en:

mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1

Si necesita más información sobre el redondeo en python, lea esto.

Avatar de usuario de Deekshant
Deekshant

Otras respuestas, especialmente la seleccionada, claramente han respondido bastante bien a esta pregunta. Pero me gustaría presentar un enfoque gráfico que también podría ser más fácil de entender, junto con el código python para realizar un módulo matemático normal en python.

Módulo de Python para Dummies

La función Modulo es una función direccional que describe cuánto tenemos que avanzar o retroceder después de los saltos matemáticos que damos durante la división sobre nuestro eje X de números infinitos. Así que digamos que estabas haciendo 7%3

ingrese la descripción de la imagen aquí

Entonces, en dirección hacia adelante, su respuesta sería +1, pero en dirección hacia atrás:

ingrese la descripción de la imagen aquí

su respuesta sería -2. Ambos son correctos matemáticamente.

De manera similar, también tendría 2 módulos para números negativos. Por ejemplo: -7%3puede dar como resultado -1 o +2 como se muestra –

ingrese la descripción de la imagen aquí

Dirección de avance


ingrese la descripción de la imagen aquí

Dirección hacia atrás


En matemáticas, elegimos saltos hacia adentro, es decir, dirección hacia adelante para un número positivo y dirección hacia atrás para números negativos.

Pero en Python, tenemos una dirección de avance para todas las operaciones de módulo positivo. Por lo tanto, su confusión –

>>> -5 % 4 
3

>>> 5 % 4
1

Aquí está el código de python para el módulo de tipo de salto hacia adentro en python:

def newMod(a,b):
    res = a%b
    return res if not res else res-b if a<0 else res

que daría –

>>> newMod(-5,4)
-1

>>> newMod(5,4)
1

Muchas personas se opondrían al método de salto hacia adentro, pero mi opinión personal es que este es mejor.

Avatar de usuario de Bob Stein
bob stein

Como se señaló, el módulo de Python hace un bien razonado excepción 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 % módulo a menudo es (como en math.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
  • Pitón % siempre da salida a cero o positivo*
  • Pitón // siempre redondea hacia el infinito negativo

* … siempre que el operando correcto sea positivo. Por otro lado 11 % -10 == -9

  • Gracias tu ejemplo me hizo entenderlo 🙂

    – Lamis

    16 de octubre de 2016 a las 6:51

Avatar de usuario de David Thornley
david thornley

No existe una mejor manera de manejar la división de enteros y las modificaciones con números negativos. Sería bueno si a/b era de la misma magnitud y signo opuesto de (-a)/b. Sería bueno si a % b era de hecho un módulo b. Ya que realmente queremos a == (a/b)*b + a%blos dos primeros son incompatibles.

Cuál mantener es una pregunta difícil, y hay argumentos para ambos lados. C y C++ redondean la división de enteros hacia cero (entonces a/b == -((-a)/b)), y aparentemente Python no lo hace.

  • Gracias tu ejemplo me hizo entenderlo 🙂

    – Lamis

    16 de octubre de 2016 a las 6:51

Avatar de usuario de רועי שמש
רועי שמש

Puedes usar:

result = numpy.fmod(x,y)

mantendrá el cartel, mira documentación numpy fmod().

¿Ha sido útil esta solución?