¿Matemáticas incorrectas con Python?

78

Acabo de comenzar con Python, por lo que probablemente este sea mi error, pero ...

Estoy probando Python. Me gusta usarlo como calculadora y estoy trabajando lentamente en algunos tutoriales.

Hoy me encontré con algo extraño. Quería averiguar 2013 * 2013, pero escribí algo incorrecto y escribí 2013 * 013, y obtuve esto:

>>> 2013*013
22143

Verifiqué con mi calculadora, ¡y 22143 es la respuesta incorrecta! Se supone que 2013 * 13 es 26169.

¿Por qué Python me da una respuesta incorrecta? Mi vieja calculadora Casio no hace esto ...

James Elegan
fuente
2
relacionado: stackoverflow.com/q/13013638/748858
mgilson
6
+1 por notarlo. Sabía que era un número octal, pero si no lo hubiera sabido, ahora pensaría que 2013 * 13 era 22143. ¿Cómo descubrió que era la respuesta incorrecta?
11684
11
Hice matemáticas mentales durante un tiempo en la escuela secundaria, y pensé que 22143 era un poco más pequeño de lo que debería ser. Así que lo verifiqué con mi confiable calculadora.
James Elegan
2
+1 por confiar en tu buena cabeza.
Sean Allred
13
@ 11684 Si el último dígito de ambos números es 3, el último dígito del producto debe ser 9. matemáticas de la escuela primaria ...
Aleksandar

Respuestas:

137

Debido a la aritmética octal, 013 es en realidad el número entero 11.

>>> 013
11

Con un cero a la izquierda, 013se interpreta como un número de base 8 y 1 * 8 1 + 3 * 8 0 = 11.

Nota: este comportamiento se cambió en Python 3 . Aquí hay una cita particularmente apropiada de PEP 3127

La representación octal predeterminada de los enteros es silenciosamente confusa para las personas que no están familiarizadas con los lenguajes tipo C. Es extremadamente fácil crear inadvertidamente un objeto entero con el valor incorrecto, porque '013' significa 'decimal 11', no 'decimal 13', para el lenguaje Python en sí, que no es el significado que la mayoría de los humanos asignarían a este literal. .

wim
fuente
14
@JamesElegan: Quizás esa sea una razón por la que Python 3 hace que la 0123sintaxis sea ilegal y siempre requiere 0o123.
Tim Pietzcker
3
Sí, el 0prefijo seguido de 0-8 es octal. 0xEl prefijo seguido de 0-9a-f es hexadecimal.
Frambot
97
¿Por qué los programadores siempre confunden Halloween y Navidad? Porque DEC25 == OCT31! Nyuk nyuk nyuk.
Frambot
16
@JoeFrambach, 0prefijo seguido por 0- 7 es octal :)
Marcos Tolonen
5
El dictador benevolente no copió de Lisp correctamente la primera vez. Estas cosas deben ser fuertes y claras: #xFF, # o777, # b1011.
Kaz
36

013es un literal entero octal (equivalente al literal entero decimal 11), debido al 0 inicial.

>>> 2013*013
22143
>>> 2013*11
22143
>>> 2013*13
26169

Es muy común (ciertamente en la mayoría de los lenguajes con los que estoy familiarizado) que los literales enteros octales comiencen con 0y los literales enteros hexadecimales comiencen con 0x. Debido a la confusión exacta que experimentó, Python 3 genera un SyntaxError:

>>> 2013*013
  File "<stdin>", line 1
    2013*013
           ^
SyntaxError: invalid token

y requiere una 0oo en su 0Olugar:

>>> 2013*0o13
22143
>>> 2013*0O13
22143 
Darshan Rivka Whittle
fuente
¡Gracias por la respuesta! Creo que esto octal es un poco confuso, pero al menos ahora lo sé :)
James Elegan
3
Eres muy bienvenido. Como se señaló en la respuesta mía y de @ wim, la comunidad de Python está haciendo todo lo posible para minimizar la confusión de los novatos en torno a los literales octales con Python 3. Aún así, es algo muy bueno tener en cuenta; puede estar seguro de que se encontrará con Literales octales con prefijo 0 nuevamente, ya sea en Python 2.X o en algún otro idioma.
Darshan Rivka Whittle
2
el PEP 3127 es una lectura un poco divertida a este respecto ... por ejemplo, "un nuevo usuario de Python puede (actualmente) estar desconcertado por el retraso en el descubrimiento de que sus números no funcionan correctamente, podemos solucionarlo explicándole inmediatamente que Python no le gustan los ceros iniciales (¡con suerte con un mensaje razonable!), o podemos delegar esta experiencia de enseñanza al intérprete de JavaScript en el navegador Internet Explorer, y dejar que intente depurar su problema allí ".
wim
5

Esto se trata principalmente de expandir un poco la respuesta de @ Wim, pero Python indica la base de literales enteros usando ciertos prefijos. Sin un prefijo, los números enteros se interpretan como en base 10. Con un "0x", el número entero se interpretará como un int hexadecimal. La especificación gramatical completa está aquí, aunque es un poco difícil de entender si no está familiarizado con las gramáticas formales: http://docs.python.org/2/reference/lexical_analysis.html#integers

Básicamente, la tabla dice que si desea un valor largo (es decir, uno que exceda la capacidad de un int normal), escriba el número seguido de la letra "L" o "l"; si desea que su número se interprete en decimal, escriba el número normalmente (sin 0 a la izquierda); si desea que se interprete en octal, antepóngalo con "0", "0o" o "0O"; si lo desea en hexadecimal, anteponga "0x"; y si lo desea en binario, anteponga "0b" o "0B".

Kyle Strand
fuente
Python parece estar agregando esa L automáticamente, cuando ingreso números realmente grandes (como 9999999999999999999999999, pero no como 3333333333). ¿Hay algún momento en el que tenga que agregarlo yo mismo?
James Elegan
@JamesElegan solo si estás usando una versión increíblemente antigua de Python. Y en Python 3, la L desapareció por completo, al igual que todas las demás distinciones entre los tipos int y long.
lvc
Python 2.7 no es increíblemente viejo, ¿lo supongo? Así que nunca necesito agregar la L. (sigo escuchando cosas buenas sobre Python 3, ¿tal vez debería instalarlo y usarlo?)
James Elegan
@JamesElegan No puedo encontrar ninguna información exacta sobre qué versión anterior requería el sufijo para literales que eran más grandes de lo que podían caber en un int(y en realidad podría estar equivocado acerca de que haya uno): mi propia memoria se remonta a ser bastante seguro que 2.4 no lo necesitaba. Pero sí, generalmente vale la pena pasar a Python 3 si no depende de ninguna biblioteca que aún no se haya adaptado.
lvc
Python 2.7 es la versión más reciente de Python 2; de hecho, 2.7.4 fue lanzado este fin de semana. Python 3 es sustancialmente diferente de Python 2, pero en última instancia, la mayoría del código de Python se escribirá como código de Python 3 en un futuro no muy lejano, o al menos, ese parece ser el objetivo. Entonces, si recién está comenzando y puede elegir cuál aprender, recomendaría 3 o ambos 2 y 3.
Kyle Strand