13

In a truly surreal experience, I have spent 20 minutes on a task I thought would take 20 seconds.

I want to use decimals with 3 or more places. I cannot get anything over 1 place, and even in that case it's nonsense.

For example, I am unable to get 1/3 to show as anything other than 0 or 0.0.

Googling led me to Decimal, but Decimal also failed to help.

Please end this torture and tell me what I have to do to get 1/3 to show up as .333!

Edit Thank you all for clearing that up! Apparently computer scientists have invented something called integer division to confuse and irritate mathematicians. Thank you for being kind enough to dissipate my confusion.

Levon
  • 138,105
  • 33
  • 200
  • 191
rschwieb
  • 746
  • 2
  • 16
  • 41
  • You mean something like `'%.3f' % (1.0/3)` is what you need? – jogojapan Jul 15 '12 at 00:47
  • Python is unique from many other languages in that you don't need to explicitly declare what kind of information a variable contains. (It's "duck typed") In this case, when you divide two integers, you get back a result that is also an integer, aka the answer rounded down. This behavior in python 2.x was so annoying that they changed it in python 3. The solution is to always be careful about how you declare variables. Either include a decimal point in one number to declare that you want a non-integer answer (1./3 is sufficient), or explicitly change the type via float(1)/float(3) – abought Jul 15 '12 at 00:53
  • 1
    @abought: Though to be fair, its also nice to know that the result of an operation between two ints is the same type and not a different type. – jdi Jul 15 '12 at 00:54
  • 1
    @jdi: It's comforting to programmers, and I can see some edge cases where this behavior would be useful. But for scripting and calculation applications, having to train users to type "1./3." is a giant headache. The existence of debate is a testament to the broad adoption of python. :) – abought Jul 15 '12 at 01:00

5 Answers5

22

In Python 2, 1/3 does integer division because both operands are integers. You need to do float division:

1.0/3.0

Or:

from __future__ import division

Which will make / do real division and // do integer division. This is the default as of Python 3.

lvc
  • 34,233
  • 10
  • 73
  • 98
Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • `//` is always floor division, even without the future import (and, importantly, *regardless of the type of operands* - `1.0//3 == 0`, although Py2 still gives it back as a float). – lvc Jul 15 '12 at 02:30
  • @lvc yes, I know, I was just mentioning it to let him know that integer division is still possible even with `from __future__ import division` – Seth Carnegie Jul 15 '12 at 04:10
7

If you divide 2 integers you'll end up with a truncated integer result (i.e., any fractional part of the result is discarded) which is why

 1 / 3

gives you:

 0

To avoid this problem, at least one of the operands needs to be a float. e.g., 1.0 / 3 or 1 / 3.0 or (of course) 1.0 / 3.0 will avoid integer truncation. This behavior is not unique to Python by the way.

(Edit: As mentioned in a helpful comment below by @Ivc if one of the integer operands is negative, the result is floor()'ed instead - see this article on the reason for this).

Also, there might be some confusion about the internal and external represenation of the number. The number is what it is, but we can determine how it's displayed.

You can control the external representation with formatting instructions. For instance a number can be displayed with 5 digits after the decimal point like this:

n = 1/3.0

print '%.5f' %n
0.33333

To get 15 digits after the decimal.

print '%.15f' %n
0.333333333333333

Finally, there is a "new and improved" way of formatting strings/numbers using the .format() function which will be around for probably much longer than the %-formatting I showed above. An example would be:

print 'the number is {:.2}'.format(1.0/3.0)

would give you:

the number is 0.33
Levon
  • 138,105
  • 33
  • 200
  • 191
  • I think you missed the fact that the op was dividing ints – jdi Jul 15 '12 at 00:48
  • @jdi oh, I guess I didn't even consider the interger trunctation to be part of the problem, but the fact that OP wasn't getting more than one digit after the decimal point. Thanks for pointing this out, I'll add a note to my answer about truncation. – Levon Jul 15 '12 at 00:50
  • I actually don't even know how the OP was seeing 0.0 to be honest. – jdi Jul 15 '12 at 00:51
  • @jdi Yes, that threw me off too. – Levon Jul 15 '12 at 00:52
  • 1
    @jdi I had been trying float(1/3) in a vain attempt to stop 1/3 rounding to 0 – rschwieb Jul 15 '12 at 00:52
  • Ah, that was my guess. It was just converted the int result to a float. – jdi Jul 15 '12 at 00:53
  • 1
    @rschwieb Ah .. yes, right idea, but unfortunately, not-so-right order of operations :-) – Levon Jul 15 '12 at 00:53
  • @Levon Faced with the Lovecraftian maw of computer science logic, I was willing to try anything! – rschwieb Jul 15 '12 at 00:55
  • @rschwieb ha ha .. I *know*, I've been there myself :) – Levon Jul 15 '12 at 00:58
  • @rschwieb Don't feel bad, every programmer runs into this, regardless of language .. see [this](http://stackoverflow.com/a/11060283/1209279), C programmers aren't immune from this either. Same principles apply – Levon Jul 15 '12 at 01:05
  • @Levon only new C programmers are susceptible to cases of integer division; the immunity builds up pretty quickly. – Seth Carnegie Jul 15 '12 at 01:12
  • 1
    @SethCarnegie True that :-) .. once you've experienced problems due to this, you tend to remember. Re C, I don't even want to think about how many hours I once spent as a newbie on `if (i = 0)` when I really meant `if (i == 0)` .. argh. – Levon Jul 15 '12 at 01:14
  • 1
    Integer division doesn't truncate, it rounds down: `-1//3` is -1. This differs from the C behaviour, which *does* truncate (`-1/3` is 0). – lvc Jul 15 '12 at 02:41
  • @ivc Interesting, I guess I never dealt with this and negative numbers. I've always heard this as referred to as "truncation". I just found [this](http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html). I'll add a note to my answer - thanks (I learned something too in the process. – Levon Jul 15 '12 at 02:50
2

Your value needs to be a floating point

In [1]: 1/3
Out[1]: 0

In [2]: 1/3.0
Out[2]: 0.33333333333333331

or

In [1]: from __future__ import division

In [2]: 1/3
Out[2]: 0.33333333333333331
Andy Casey
  • 307
  • 1
  • 2
  • 11
2

In Python2 you have to specify at least one of the operands as a floating point number. To take just 3 decimals you can use the round() method:

>>> a = 1.0 / 3
>>> round(a, 3)
0.333

In Python3 it seems they don't perform integer division by default, so you can do:

>>> a = 1/3
>>> round(a, 3)
0.333
dave
  • 2,199
  • 1
  • 16
  • 34
1

Use Decimal. You can got 100 digit behind the dot.

from decimal import *
getcontext().prec = 100
Decimal(1)/Decimal(3)
recobayu
  • 581
  • 4
  • 6