3

I recently transitioned one script to use Python 2.7 from 3.4 (at the request of a colleague), and I'm finding that the math.ceil function does not work the same...

When I divide 5/2 and round it up with math.ceil(), I expect to get math.ceil(5/2) = 3.

Given the following code:

from __future__ import print_function
import math

a = 5
b = 2
c = math.ceil(a/b)

print("Ceiling output: {}".format(c))

Python 2.7 will report 2 as the answer, Python 3.4 reports 3 as expected.

Why is this?

I know I can get 2.7 to work if I cast a and b as float:

c = math.ceil(float(a)/float(b)

However, casting the division won't work either:

c = math.ceil(float(a/b))

How does 3.4 work around this?

Finding this makes me question how much math I need to re-check in the 2.7 version of the script.

Catsunami
  • 569
  • 6
  • 20
  • Relevant: https://stackoverflow.com/questions/183853/in-python-2-what-is-the-difference-between-and-when-used-for-division#183870 – dfundako Jun 07 '18 at 17:25

3 Answers3

7

It's because the division operator / is integer division in Python 2.7. Note that the function arguments are fully evaluated before the function call, so math.ceil was actually an innocent bystander here.

math.ceil(5/2)  # same as math.ceil(2)!

To get the Python 3 behaviour in 2.7, use a future statement:

from __future__ import division
wim
  • 338,267
  • 99
  • 616
  • 750
2

This is because / in Python 2 is regular integer division.

If you want the / operator to behavethe way it does in Python 3 then add this line to your imports from __future__ import division.

Also, note that if you wanted to regular integer division in Python 3 use // instead of /.

after you add the import you will find that

In [16]: from __future__ import division

In [17]: a = 5

In [18]: b = 2

In [19]: import math

In [20]: c = math.ceil(a/b)

In [21]: c
Out[21]: 3.0
Srini
  • 1,619
  • 1
  • 19
  • 34
1

This is not a rounding issue, it is a default numeric type issue. Python 2.7 looks at the numbers and sees integers. Since all numbers involved are integers, 5/2 ==> 2 instead of 2.5, so ceil() is 2. Note that the / operator WILL do floating point division too, provided at least one value is floating point. So if x = 5.0 instead of 5 or if y = 2.0 instead of 2 then you will get 2.5 ==> ceil() = 3.