78

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 2013*2013, but I wrote the wrong thing and wrote 2013*013, 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...

wim
  • 338,267
  • 99
  • 616
  • 750
James Elegan
  • 948
  • 1
  • 7
  • 15
  • 2
    related: http://stackoverflow.com/q/13013638/748858 – mgilson Apr 09 '13 at 06:14
  • 6
    +1 for actually noticing. I knew it was an octal number, but if I would not have known, I would now think 2013*13 was 22143. How did you discover it was the wrong answer? – 11684 Apr 09 '13 at 06:45
  • 11
    I did mental math for a while back in high school, and I thought 22143 was a bit smaller than it should be. So I checked with my trusty calculator. – James Elegan Apr 09 '13 at 06:46
  • 2
    +1 for trusting your good ole' noggin. – Sean Allred Apr 09 '13 at 11:52
  • 13
    @11684 If the last digit in both numbers is 3, the last digit of the product must be 9. elementary school mathematics... – Aleksandar Apr 09 '13 at 12:29
  • 1) I'm lazy; 2) Why would I recalculate something my computer I calculated, while I know for sure my computer can do maths a lot better than me? 3) I never learned that kind of tricks, I never needed them. @Aleksandar – 11684 Apr 09 '13 at 16:29
  • Interesting... How did you end up with a preceding 0 when you were intending a decimal number? – froggythefrog Apr 09 '13 at 18:05
  • 2
    @11684, an even simpler mental check is to think "2013 is approximately 2000, and 13 * 2 = 26, so the result should be about 26000". – Ben Lee Apr 09 '13 at 21:40
  • I don't doubt I would discover it is too small without calculator if I had a reason to check. But why would you perform such a check if you trust your Python interpreter? – 11684 Apr 10 '13 at 10:01
  • When you think there's something wrong with the universe you might be right but probably not. The same with compilers, especially the simple stuff like math http://blogs.msdn.com/b/ericlippert/archive/2011/04/25/maybe-there-s-something-wrong-with-the-universe-but-probably-not.aspx – Rune FS Apr 10 '13 at 10:50

4 Answers4

137

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 1*81 + 3*80 = 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.

wim
  • 338,267
  • 99
  • 616
  • 750
36

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 
Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
  • Thanks for the answer! I think this octal thing is a bit confusing, but at least now I know about it :) – James Elegan Apr 09 '13 at 05:58
  • 3
    You're very welcome. As noted in mine and @wim's answer, the Python community is doing what they can to minimize newbie confusion around octal literals with Python 3. Still, it's a very good thing to be aware of -- you can be sure you'll run into 0-prefixed octal literals again, whether in Python 2.X or some other language. – Darshan Rivka Whittle Apr 09 '13 at 06:18
  • 2
    the PEP 3127 is a slightly amusing read in this respect ... e.g. "a new Python user may (currently) be mystified at the delayed discovery that his numbers don't work properly, we can fix it by explaining to him immediately that Python doesn't like leading zeros (hopefully with a reasonable message!), or we can delegate this teaching experience to the JavaScript interpreter in the Internet Explorer browser, and let him try to debug his issue there." – wim Apr 09 '13 at 08:21
7

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

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
5

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".

Kyle Strand
  • 15,941
  • 8
  • 72
  • 167
  • Python seems to be adding that L automatically, when I enter really big numbers (like 9999999999999999999999999, but not like 3333333333). Is there any time when I would have to add it myself? – James Elegan Apr 09 '13 at 06:05
  • @JamesElegan only if you're using an insanely old version of Python. And in Python 3, the L is gone completely, as are all the other distinctions between int and long types. – lvc Apr 09 '13 at 06:12
  • Python 2.7 is not insanely old, I take it? So I never need to add the L. (I keep hearing good things about Python 3, maybe I should just install and use that?) – James Elegan Apr 09 '13 at 06:14
  • @JamesElegan I can't find any exact information on which previous version required the suffix for literals that were bigger than could fit in an `int` (and I might actually be wrong about there being one) - my own memory goes back as far as being fairly sure that 2.4 didn't need it. But yes, Python 3 is generally worthwhile to move to if you don't depend on any libraries that haven't been ported yet. – lvc Apr 09 '13 at 06:17
  • Python 2.7 is the most recent version of Python 2; in fact, 2.7.4 was released just this weekend. Python 3 is substantially different from Python 2, but ultimately most Python code will be written as Python 3 code in the not-too-distant future, or at least, that seems to be the goal. So if you're just starting out and you can choose which one to learn, I'd recommend either 3 or both 2 and 3. – Kyle Strand Apr 09 '13 at 06:36
  • The Python people have an explanation here about which version to choose: http://wiki.python.org/moin/Python2orPython3 – Kyle Strand Apr 09 '13 at 06:37
  • Heh, OK. From all the feedback I got today, I think I will try Python 3. Maybe I will have less surprises :) – James Elegan Apr 09 '13 at 06:45