¿Cuál es el resultado de% en Python?

241

¿Qué significa el %en un cálculo? Parece que no puedo entender lo que hace.

¿Calcula un porcentaje del cálculo, por ejemplo: 4 % 2aparentemente es igual a 0. ¿Cómo?

naranja
fuente

Respuestas:

304

El operador% (módulo) produce el resto de la división del primer argumento por el segundo. Los argumentos numéricos se convierten primero a un tipo común. Un argumento de cero a la derecha genera la excepción ZeroDivisionError. Los argumentos pueden ser números de coma flotante, por ejemplo, 3.14% 0.7 es igual a 0.34 (ya que 3.14 es igual a 4 * 0.7 + 0.34.) El operador de módulo siempre produce un resultado con el mismo signo que su segundo operando (o cero); El valor absoluto del resultado es estrictamente menor que el valor absoluto del segundo operando [2].

Tomado de http://docs.python.org/reference/expressions.html

Ejemplo 1: 6%2 evalúa 0porque no hay resto si 6 se divide por 2 (3 veces).

Ejemplo 2 : 7%2evalúa 1porque hay un resto de 1cuando 7 se divide por 2 (3 veces).

Para resumir eso, devuelve el resto de una operación de división, o 0si no hay resto. Entonces 6%2significa encontrar el resto de 6 dividido por 2.

meder omuraliev
fuente
77
¿Por qué todos los ejemplos tienen un número mayor a la derecha? ¿Alguien puede explicar el resultado del 2% 6 que produce 2?
wookie
8
El primer número es el numerador y el segundo es el denominador. En su ejemplo, 2 dividido entre 6 es 0 resto 2, por lo tanto, el resultado es 2.
David
44
Actualice su respuesta, hay respuestas más precisas a continuación. En C / C ++ % es para 'rem' mientras que en Python% es para 'mod'. Por ejemplo, - 21 % 4es 3 en Python.
azam
¿Puedes explicar por qué -11%5 = 4?
dahiya_boy
@dahiya_boy He agregado la explicación de GvR a mi respuesta menos votada a continuación.
Paulo Scardine
143

Algo fuera de tema, %también se usa en operaciones de formateo de cadenas como %=para sustituir valores en una cadena:

>>> x = 'abc_%(key)s_'
>>> x %= {'key':'value'}
>>> x 
'abc_value_'

Una vez más, fuera del tema, pero parece ser una característica poco documentada que me llevó un tiempo rastrear, y pensé que estaba relacionada con el cálculo del módulo de Pythons para el que esta página SO ocupa un lugar destacado.

mrmagooey
fuente
¿Existe la lógica de que% también se use como referencia de formato de cadena o es solo un accidente de la historia que ese símbolo se haya sobrecargado? ¿Debería ser esta su propia pregunta?
WAF
55
¿Mal documentado? No lo creo: Operaciones de formateo de cadenas
KurzedMetal
@KurzedMetal - %=no aparece en esa página
P. Myer Nore
@WAF Se eligió el %operador porque refleja los especificadores de porcentaje utilizados dentro de la propia cadena.
MI Wright
@ P.MyerNore Sé que esto es casi 3 años después, pero puede ayudar a otros. Lea el primer párrafo resaltado en sec. 5.6.2 vinculado anteriormente por KurzedMetal. "X% = {}" es simplemente una forma abreviada de "x = x% {...}"
Sujay Phadke
58

Una expresión como x % yevalúa el resto de x ÷ y- bueno, técnicamente es "módulo" en lugar de "recordatorio", por lo que los resultados pueden ser diferentes si se compara con otros idiomas donde %está el operador restante. Hay algunas diferencias sutiles (si está interesado en las consecuencias prácticas, consulte también "Por qué los pisos de división entera de Python" a continuación).

La precedencia es lo mismo que los operadores /(división) y *(multiplicación).

>>> 9 / 2
4
>>> 9 % 2
1
  • 9 dividido por 2 es igual a 4.
  • 4 por 2 es 8
  • 9 menos 8 es 1, el resto.

Python gotcha : dependiendo de la versión de Python que esté utilizando, %también es el operador de interpolación de cadenas (en desuso), así que tenga cuidado si viene de un lenguaje con conversión automática de tipos (como PHP o JS) donde una expresión como '12' % 2 + 3legal es: en Python resultará en lo TypeError: not all arguments converted during string formattingque probablemente será bastante confuso para usted.

[actualización para Python 3]

Comentarios del usuario n00p:

9/2 es 4.5 en python. Debe hacer una división entera de la siguiente manera: 9 // 2 si desea que Python le diga cuántos objetos completos quedan después de la división (4).

Para ser precisos, la división de enteros solía ser el valor predeterminado en Python 2 (ten en cuenta que esta respuesta es mayor que mi hijo que ya estaba en la escuela y en ese momento 2.x era mainstream):

$ python2.7
Python 2.7.10 (default, Oct  6 2017, 22:29:07)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 9 / 2
4
>>> 9 // 2
4
>>> 9 % 2
1

En los 9 / 2resultados modernos de Python 4.5:

$ python3.6
Python 3.6.1 (default, Apr 27 2017, 00:15:59)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 9 / 2
4.5
>>> 9 // 2
4
>>> 9 % 2
1

[actualizar]

El usuario dahiya_boy preguntó en la sesión de comentarios:

P. ¿Puede explicar por qué -11 % 5 = 4- dahiya_boy

Esto es raro, ¿verdad? Si intentas esto en JavaScript:

> -11 % 5
-1

Esto se debe a que en JavaScript %es el operador "restante", mientras que en Python es el operador "módulo" (matemática del reloj).

Puede obtener la explicación directamente de GvR :


Editar - dahiya_boy

En Java e iOS, -11 % 5 = -1mientras que en Python y Ruby -11 % 5 = 4.

Bueno, la mitad de la razón es explicada por Paulo Scardine , y el resto de la explicación está debajo aquí.

En Java e iOS, %da el resto, lo que significa que si divide 11% 5 da Quotient = 2 and remainder = 1y -11% 5 da Quotient = -2 and remainder = -1.

Código de muestra en iOS rápido.

ingrese la descripción de la imagen aquí

Pero cuando hablamos de Python, da un módulo de reloj. Y su trabajo con la siguiente fórmula

mod(a,n) = a - {n * Floor(a/n)}

Eso significa,

mod(11,5) = 11 - {5 * Floor(11/5)} => 11 - {5 * 2}

Entonces, mod(11,5) = 1

Y

mod(-11,5) = -11 - 5 * Floor(11/5) => -11 - {5 * (-3)}

Entonces, mod(-11,5) = 4

Código de muestra en python 3.0.

ingrese la descripción de la imagen aquí


Por qué los pisos de la división entera de Python

Me pidieron (nuevamente) hoy que explique por qué la división entera en Python devuelve el piso del resultado en lugar de truncar hacia cero como C.

Para números positivos, no hay sorpresa:

>>> 5//2
2

Pero si uno de los operandos es negativo, el resultado se anula, es decir, se redondea desde cero (hacia el infinito negativo):

>>> -5//2
-3
>>> 5//-2
-3

Esto molesta a algunas personas, pero hay una buena razón matemática. La operación de división de enteros (//) y su hermano, la operación de módulo (%), van juntas y satisfacen una buena relación matemática (todas las variables son enteras):

a/b = q with remainder r

tal que

b*q + r = a and 0 <= r < b

(suponiendo que ayb son> = 0).

Si desea que la relación se extienda para a negativo (manteniendo b positivo), tiene dos opciones: si trunca q hacia cero, r se volverá negativo, de modo que la invariante cambie a 0 <= abs (r) <de lo contrario, usted puede pasar al suelo q hacia el infinito negativo, y la invariante permanece 0 <= r <b. [actualización: arreglado este para]

En la teoría de números matemáticos, los matemáticos siempre prefieren la última opción (ver, por ejemplo, Wikipedia ). Para Python, hice la misma elección porque hay algunas aplicaciones interesantes de la operación de módulo donde el signo de un no es interesante. Considere tomar una marca de tiempo POSIX (segundos desde el comienzo de 1970) y convertirla en la hora del día. Como hay 24 * 3600 = 86400 segundos en un día, este cálculo es simplemente t% 86400. ¡Pero si expresáramos tiempos antes de 1970 usando números negativos, la regla de "truncar hacia cero" daría un resultado sin sentido! Usando la regla de piso todo funciona bien.

Otras aplicaciones que he pensado son cálculos de posiciones de píxeles en gráficos de computadora. Estoy seguro de que hay más.

Para b negativo, por cierto, todo simplemente se voltea, y el invariante se convierte en:

0 >= r > b.

Entonces, ¿por qué C no lo hace de esta manera? Probablemente el hardware no hizo esto en el momento en que C fue diseñado. Y el hardware probablemente no lo hizo de esta manera porque en el hardware más antiguo, los números negativos se representaban como "signo + magnitud" en lugar de la representación de complemento de dos utilizada en estos días (al menos para enteros). Mi primera computadora fue un mainframe de Control Data y usó el complemento de uno para enteros y flotantes. ¡Un patrón de 60 unos significaba cero negativo!

Tim Peters, quien sabe dónde están enterrados todos los esqueletos de coma flotante de Python, ha expresado cierta preocupación por mi deseo de extender estas reglas al módulo de coma flotante. Probablemente tenga razón; La regla de truncar hacia el infinito negativo puede causar pérdida de precisión para x% 1.0 cuando x es un número negativo muy pequeño. Pero eso no es suficiente para que rompa el módulo entero, y // está estrechamente acoplado a eso.

PD. Tenga en cuenta que estoy usando // en lugar de /: esta es la sintaxis de Python 3, y también se permite en Python 2 enfatizar que sabe que está invocando la división de enteros. El operador / en Python 2 es ambiguo, ya que devuelve un resultado diferente para dos operandos enteros que para un int y un flotante o dos flotantes. Pero esa es una historia totalmente separada; ver PEP 238.

Publicado por Guido van Rossum a las 9:49 a.m.

Paulo Scardine
fuente
1
Además, help(divmod)documenta la invariante q, r = divmod(x y) <==> q*y + r == x.
chepner
49

El módulo es una operación matemática, a veces descrita como "aritmética de reloj". Me parece que describirlo como un simple residuo es engañoso y confuso porque oculta la verdadera razón por la que se usa tanto en informática. Realmente se utiliza para envolver los ciclos.

Piense en un reloj: suponga que mira un reloj en tiempo "militar", donde el rango de horas va de 0:00 a 23.59. Ahora, si desea que algo suceda todos los días a medianoche, desearía que la hora actual mod 24 sea cero:

if (hora% 24 == 0):

Puedes pensar en todas las horas de la historia envolviendo un círculo de 24 horas una y otra vez y la hora actual del día es ese número infinitamente largo mod 24. Es un concepto mucho más profundo que solo un resto, es una forma matemática lidiar con los ciclos y es muy importante en informática. También se usa para envolver las matrices, lo que le permite aumentar el índice y usar el módulo para volver al principio después de llegar al final de la matriz.

jarvis01123
fuente
1
Así es como se implementa en Python:a % b = a - b * floor(a/b)
Aiman ​​Al-Eryani
7

En la mayoría de los idiomas,% se utiliza para el módulo . Python no es la excepción.

sorigal
fuente
11
Hasta donde puedo ver, Python es inusual en el sentido de que utiliza% para el módulo; Fortran, C / C ++ y Java usan% para significar el resto. (Ver stackoverflow.com/questions/13683563/… , las diferencias están en cómo se manejan los valores negativos y fraccionarios.) Los lenguajes que hacen una distinción (por ejemplo, Ada, Haskell y Scheme) usan las palabras "rem" y "mod" (o "resto" y "módulo") en lugar de%.
Jim Pivarski
55
Actualización: encontré esta gran tabla de operaciones de módulo / resto por idioma en.wikipedia.org/wiki/Modulo_operation . Python es inusual pero no único (por ejemplo, TCL y Lua comparten la convención de Python).
Jim Pivarski
5

El operador% Modulo también se puede utilizar para imprimir cadenas (al igual que en C) como se define en Google https://developers.google.com/edu/python/strings .

      # % operator
  text = "%d little pigs come out or I'll %s and %s and %s" % (3, 'huff', 'puff', 'blow down')

Esto parece desviarse del tema, pero ciertamente ayudará a alguien.

Harshit Chaudhary
fuente
4

x % ycalcula el resto de la división xdividida por ydonde el cociente es un número entero . El resto tiene el signo de y.


En Python 3 el cálculo rinde 6.75; Esto se debe a que /hace una división verdadera, no una división entera como (por defecto) en Python 2. En Python 2 1 / 4da 0, ya que el resultado se redondea hacia abajo.

La división de enteros también se puede hacer en Python 3, con el //operador, por lo tanto, para obtener el 7 como resultado, puede ejecutar:

3 + 2 + 1 - 5 + 4 % 2 - 1 // 4 + 6

Además, puede obtener la división de estilo Python en Python 2, simplemente agregando la línea

from __future__ import division

como la primera línea de código fuente en cada archivo fuente.

Antti Haapala
fuente
8
Recuerde niños #es para comentarios y //es un operador.
Mike Causer
3

Operador de módulo, se usa para la división de resto en enteros, típicamente, pero en Python se puede usar para números de coma flotante.

http://docs.python.org/reference/expressions.html

El operador% (módulo) produce el resto de la división del primer argumento por el segundo. Los argumentos numéricos se convierten primero a un tipo común. Un argumento de cero a la derecha genera la excepción ZeroDivisionError. Los argumentos pueden ser números de coma flotante, por ejemplo, 3.14% 0.7 es igual a 0.34 (ya que 3.14 es igual a 4 * 0.7 + 0.34.) El operador de módulo siempre produce un resultado con el mismo signo que su segundo operando (o cero); El valor absoluto del resultado es estrictamente menor que el valor absoluto del segundo operando [2].

wkl
fuente
3

Es una operación de módulo, excepto cuando se trata de un operador de formato de cadena estilo C antiguo, no una operación de módulo . Ver aquí para más detalles. Verá mucho de esto en el código existente.

John Machin
fuente
3

Además, hay una útil función incorporada llamada divmod:

divmod (a, b)

Tome dos números (no complejos) como argumentos y devuelva un par de números que consisten en su cociente y el resto al usar la división larga.

warvariuc
fuente
2

Sé consciente de

(3 +2 + 1 - 5) + (4 % 2) - (1/4) + 6

incluso con los corchetes resulta en 6.75 en lugar de 7 si se calcula en Python 3.4.


Y el operador '/' tampoco es tan fácil de entender (python2.7): intente ...

- 1/4

1 - 1/4

Esto es un poco fuera de tema aquí, pero debe tenerse en cuenta al evaluar la expresión anterior :)

bernhard
fuente
2
¿Cómo sería esto alguna vez 7? Se simplifica a (1)+(0)-(0.25)+(6).
J.Steve
1

Fue difícil para mí encontrar fácilmente casos de uso específicos para el uso de% en línea, por ejemplo, ¿por qué la división de módulo fraccional o la división de módulo negativa dan como resultado la respuesta que hace? Espero que esto ayude a aclarar preguntas como esta:

División de módulos en general:

La división de módulo devuelve el resto de una operación de división matemática. Se hace de la siguiente manera:

Digamos que tenemos un dividendo de 5 y un divisor de 2, la siguiente operación de división sería (equivalente a x):

dividend = 5
divisor = 2

x = 5/2 
  1. El primer paso en el cálculo del módulo es realizar una división entera:

    x_int = 5 // 2 (la división de enteros en python usa doble barra)

    x_int = 2

  2. A continuación, la salida de x_int se multiplica por el divisor:

    x_mult = x_int * divisor x_mult = 4

  3. Por último, el dividendo se resta de x_mult

    dividendo - x_mult = 1

  4. La operación de módulo, por lo tanto, devuelve 1:

    5% 2 = 1

Aplicación para aplicar el módulo a una fracción

Example: 2 % 5 

El cálculo del módulo cuando se aplica a una fracción es el mismo que el anterior; Sin embargo, es importante tener en cuenta que la división entera dará como resultado un valor de cero cuando el divisor es mayor que el dividendo:

dividend = 2 
divisor = 5

La división entera da como resultado 0 mientras que; por lo tanto, cuando se realiza el paso 3 anterior, el valor del dividendo se transfiere (se resta de cero):

dividend - 0 = 2  —> 2 % 5 = 2 

Aplicación para aplicar el módulo a un negativo

La división de piso ocurre en la cual el valor de la división entera se redondea al valor entero más bajo:

import math 

x = -1.1
math.floor(-1.1) = -2 

y = 1.1
math.floor = 1

Por lo tanto, cuando haces una división entera, ¡puedes obtener un resultado diferente al esperado!

La aplicación de los pasos anteriores en el siguiente dividendo y divisor ilustra el concepto de módulo:

dividend: -5 
divisor: 2 

Paso 1: aplicar división entera

x_int = -5 // 2  = -3

Paso 2: Multiplica el resultado de la división entera por el divisor

x_mult = x_int * 2 = -6

Paso 3: reste el dividendo de la variable multiplicada, observe el doble negativo.

dividend - x_mult = -5 -(-6) = 1

Por lo tanto:

-5 % 2 = 1
N.Atanasov
fuente
0

El operador% (módulo) produce el resto de la división del primer argumento por el segundo. Los argumentos numéricos se convierten primero a un tipo común.

3 + 2 + 1 - 5 + 4% 2 - 1/4 + 6 = 7

Esto se basa en la precedencia del operador.

usuario225312
fuente
0

%es modulo . 3 % 2 = 1,4 % 2 = 0

/ es (un entero en este caso) división, entonces:

3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
1 + 4%2 - 1/4 + 6
1 + 0 - 0 + 6
7
Khachik
fuente
0

Módulo: divide el operando de la izquierda por el operando de la derecha y devuelve el resto.

Si ayuda:

1:0> 2%6
=> 2
2:0> 8%6
=> 2
3:0> 2%6 == 8%6
=> true

... y así.

gr8scott06
fuente
0

He descubierto que la forma más fácil de comprender el operador del módulo (%) es a través de una división larga. Es el resto y puede ser útil para determinar que un número sea par o impar:

4%2 = 0

  2
2|4
 -4
  0


11%3 = 2

  3
3|11
 -9
  2
JJJ
fuente
da el resto de una división no mucho para
asimilar