Wrong math with Python?

PythonPython 2.7Math

Python Problem Overview


Just starting out with Python, so this is probably my mistake, but...

I'm trying out Python. I like to use it as a calculator, and I'm slowly working through some tutorials.

I ran into something weird today. I wanted to find out 20132013, but I wrote the wrong thing and wrote 2013013, and got this:

>>> 2013*013
22143

I checked with my calculator, and 22143 is the wrong answer! 2013 * 13 is supposed to be 26169.

Why is Python giving me a wrong answer? My old Casio calculator doesn't do this...

Python Solutions


Solution 1 - Python

Because of octal arithmetic, 013 is actually the integer 11.

>>> 013
11

With a leading zero, 013 is interpreted as a base-8 number and 181 + 380 = 11.

Note: this behaviour was changed in python 3. Here is a particularly appropriate quote from PEP 3127

> The default octal representation of integers is silently confusing to > people unfamiliar with C-like languages. It is extremely easy to > inadvertently create an integer object with the wrong value, because > '013' means 'decimal 11', not 'decimal 13', to the Python language > itself, which is not the meaning that most humans would assign to this > literal.

Solution 2 - Python

013 is an octal integer literal (equivalent to the decimal integer literal 11), due to the leading 0.

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

It is very common (certainly in most of the languages I'm familiar with) to have octal integer literals start with 0 and hexadecimal integer literals start with 0x. Due to the exact confusion you experienced, Python 3 raises a SyntaxError:

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

and requires either 0o or 0O instead:

>>> 2013*0o13
22143
>>> 2013*0O13
22143 

Solution 3 - Python

Python's 'leading zero' syntax for octal literals is a common gotcha:

Python 2.7.3
>>> 010
8

The syntax was changed in Python 3.x http://docs.python.org/3.0/whatsnew/3.0.html#integers

Solution 4 - Python

This is mostly just expanding on @Wim's answer a bit, but Python indicates the base of integer literals using certain prefixes. Without a prefix, integers are interpreted as being in base-10. With an "0x", the integer will be interpreted as a hexadecimal int. The full grammar specification is here, though it's a bit tricky to understand if you're not familiar with formal grammars: http://docs.python.org/2/reference/lexical_analysis.html#integers

The table essentially says that if you want a long value (i.e. one that exceeds the capacity of a normal int), write the number followed by the letter "L" or "l"; if you want your number to be interpreted in decimal, write the number normally (with no leading 0); if you want it interpreted in octal, prefix it with "0", "0o", or "0O"; if you want it in hex, prefix it with "0x"; and if you want it in binary, prefix it with "0b" or "0B".

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames EleganView Question on Stackoverflow
Solution 1 - PythonwimView Answer on Stackoverflow
Solution 2 - PythonDarshan Rivka WhittleView Answer on Stackoverflow
Solution 3 - PythonColonel PanicView Answer on Stackoverflow
Solution 4 - PythonKyle StrandView Answer on Stackoverflow