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 3
en lugar de, digamos, -1
?
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
yint
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
a
positivob
, mientras que los suelos de Python. siempre es cierto queabs(r) < b
y ceil iffr <= 0
.–Evgeni Sergeev
22 de abril de 2014 a las 7:43
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.
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
Entonces, en dirección hacia adelante, su respuesta sería +1, pero en dirección hacia atrás:
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%3
puede dar como resultado -1 o +2 como se muestra –
Dirección de avance
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.
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
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%b
los 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
רועי שמש
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