Pregunta

¿Puedes decirme cuánto es? (-2) % 5?Según mi intérprete de Python es 3, pero ¿tiene una explicación inteligente para esto?

He leído que en algunos idiomas el resultado puede depender de la máquina, pero no estoy seguro.

¿Fue útil?

Solución

Por cierto:la mayoría de los lenguajes de programación no estarían de acuerdo con Python y darían el resultado -2.Dependiendo de la interpretación del módulo, esto es correcto.Sin embargo, la definición matemática más aceptada establece que el módulo de a y b es el resto (estrictamente positivo) r de la división de a / b.Más precisamente, 0 <= r < b por definición.

Otros consejos

El resultado de la operación del módulo en negativos parece depender del lenguaje de programación y aquí hay una lista http://en.wikipedia.org/wiki/Modulo_operation

Su intérprete de Python es correcto.Una forma (estúpida) de calcular un módulo es restar o sumar el módulo hasta que el valor resultante esté entre 0 y (módulo − 1).

p.ej.:13 mod 5 = (13 − 5) mod 5 = (13 − 10) mod 5 = 3

o en tu caso:−2 mod 5 = (−2 + 5) mod 5 = 3

Como dice la documentación en Operaciones aritméticas binarias, Python asegura que:

Los operadores de división de enteros y módulo están conectados por la siguiente identidad: x == (x/y)*y + (x%y).La división de enteros y el módulo también están conectados con la función incorporada divmod(): divmod(x, y) == (x/y, x%y).

Y verdaderamente,

>>> divmod(-2, 5)
(-1, 3).

Otra forma de visualizar la uniformidad de este método es calcular divmod para una pequeña secuencia de números:

>>> for number in xrange(-10, 10):
...     print divmod(number, 5)
...
(-2, 0)
(-2, 1)
(-2, 2)
(-2, 3)
(-2, 4)
(-1, 0)
(-1, 1)
(-1, 2)
(-1, 3)
(-1, 4)
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(1, 4)

Bueno, 0 % 5 debería ser 0, ¿verdad?

-1 % 5 debería ser 4 porque ese es el siguiente dígito permitido que va en dirección inversa (es decir, no puede ser 5, ya que está fuera de rango).

Y siguiendo esa lógica, -2 debe ser 3.

La forma más fácil de pensar en cómo funcionará es seguir sumando o restando 5 hasta que el número esté entre 0 (inclusive) y 5 (exclusivo).

No estoy seguro de la dependencia de la máquina; nunca he visto una implementación que lo fuera, pero no puedo decir que nunca se haya realizado.

Como se explica en otras respuestas, hay muchas opciones para una operación de módulo con valores negativos.En general, diferentes lenguajes (y diferentes arquitecturas de máquina) darán resultados diferentes.

De acuerdo con la manual de referencia de pitón,

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.

es la elección tomada por Python.Básicamente, el módulo se define para que esto siempre se cumpla:

x == (x/y)*y + (x%y)

entonces tiene sentido que (-2)%5 = -2 - (-2/5)*5 = 3

Bueno, -2 dividido por 5 sería 0 con un resto de 3.No creo que eso deba depender mucho de la plataforma, pero he visto cosas más extrañas.

Efectivamente son 3.En aritmética modular, un módulo es simplemente el resto de una división y el resto de -2 dividido por 5 es 3.

El resultado depende del idioma.Python devuelve el signo del divisor, donde por ejemplo c# devuelve el signo del dividendo (es decir.-2 % 5 devuelve -2 en c#).

Una explicación podría ser que los números negativos se almacenan usando complemento a 2.Cuando el intérprete de Python intenta realizar la operación de módulo, la convierte a un valor sin signo.Como tal, en lugar de hacer (-2) % 5, en realidad calcula 0xFFFF_FFFF_FFFF_FFFD % 5, que es 3.

Tenga cuidado de no confiar en este comportamiento de modificación en C/C++ en todos los sistemas operativos y arquitecturas.Si no recuerdo mal, intenté confiar en el código C/C++ como

float x2 = x % n;

para mantener x2 en el rango de 0 a n-1, pero aparecían números negativos cuando compilaba en un sistema operativo, pero las cosas funcionaban bien en otro sistema operativo.¡Esto hizo que la depuración fuera un mal momento ya que solo ocurría la mitad del tiempo!

Parece haber una confusión común entre los términos "módulo" y "resto".

En matemáticas, un resto debe siempre definirse consistente con el cociente, de modo que si a / b == c rem d entonces (c * b) + d == a.Dependiendo de cómo redondees tu cociente, obtendrás residuos diferentes.

Sin embargo, el módulo siempre debería dar un resultado. 0 <= r < divisor, que solo es consistente con la división de redondeo a menos infinito si permite números enteros negativos.Si la división se redondea hacia cero (lo cual es común), el módulo y el resto solo son equivalentes para valores no negativos.

Algunos lenguajes (notablemente C y C++) no definen los comportamientos de redondeo/resto requeridos y % es ambiguo.Muchos definen el redondeo como hacia cero, pero utilizan el término módulo cuando el resto sería más correcto.Python es relativamente inusual porque redondea a infinito negativo, por lo que el módulo y el resto son equivalentes.

Ada se acerca a cero IIRC, pero tiene ambos mod y rem operadores.

La política de C tiene como objetivo permitir a los compiladores elegir la implementación más eficiente para la máquina, pero en mi opinión es una optimización falsa, al menos en estos días.Un buen compilador probablemente podrá usar la equivalencia para la optimización siempre que no pueda ocurrir un número negativo (y casi con certeza si usa tipos sin signo).Por otro lado, cuando pueden aparecer números negativos, es casi seguro que le importen los detalles: por razones de portabilidad, debe utilizar algoritmos y/o comprobaciones excesivamente diseñados con mucho cuidado para garantizar que obtiene los resultados que desea, independientemente del redondeo y el resto. comportamiento.

En otras palabras, la ganancia de esta "optimización" es en su mayoría (si no siempre) una ilusión, mientras que en algunos casos hay costos muy reales, por lo que es una optimización falsa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top