35

I need to ceil and floor 3/2 result (1.5) without using import math.

math.floor(3/2) => 3//2 math.ceil(3/2) => ?

OK, here is the problem: to sum all numbers 15 + 45 + 15 + 45 + 15 ... with N items.

sum = (n//2) * 5 + int(n/2) * 15

zooks
  • 525
  • 1
  • 4
  • 12
  • wrong result for 4/2 – zooks Sep 14 '15 at 07:03
  • 3
    Why not just use the `math` library? – Ffisegydd Sep 14 '15 at 07:05
  • 1
    for education purposes – zooks Sep 14 '15 at 07:06
  • Believe me, I tried. BTW I used PHP before, now I'm learning Python :) – zooks Sep 14 '15 at 07:12
  • 3
    Use the ceiling division operator, `--0--`! This converts floor division to ceiling division. For example, `--0-- 3//2` gives the ceiling of `3/2`. Try it if you don't believe me! (Okay, so you could spell it without the leading `--`, but it looks better with it.) – Mark Dickinson Sep 14 '15 at 07:16
  • @Ffisegydd: There's at least one good reason to avoid the math library here, which is that by going via floating-point you can lose precision (and get the wrong answer as a result). – Mark Dickinson Sep 14 '15 at 07:20
  • @zooks: More seriously, use the fact that `ceiling(x)` == `-floor(-x)` for any real number `x`. – Mark Dickinson Sep 14 '15 at 07:21
  • Does this answer your question? [Is there a ceiling equivalent of // operator in Python?](https://stackoverflow.com/questions/14822184/is-there-a-ceiling-equivalent-of-operator-in-python) – user202729 Oct 01 '21 at 12:33

5 Answers5

71
>>> 3/2
1.5
>>> 3//2 # floor
1
>>> -(-3//2) # ceil
2
xyres
  • 20,487
  • 3
  • 56
  • 85
bakar
  • 1,152
  • 2
  • 11
  • 20
  • 5
    funny that `>>>math.ceil(4.0000000000000001/2)` is 2, but `>>>math.ceil(4.000000000000001/2)` is 3 – soshial Dec 29 '17 at 13:00
  • 5
    But not surprising, when you consider that `4.0000000000000001 == 4.0` is `True` but `4.000000000000001 == 4.0` is False – FiddleStix Dec 17 '21 at 12:15
  • 2
    based on two comments above, is it safe to say that those two methods are not reliable? – farisfath25 Dec 19 '22 at 08:15
  • 1
    @farisfath25 No, the functions are not the issue. It is always unsafe to rely on more bits of precision in a floating-point number than are guaranteed to be accurate. At least one of those numbers cannot be represented perfectly in the floating-point system used by Python and/or the representation available on the particular processor it is running on. If you need perfect precision, you must use an arbitrary-width representation. – Matthew Read Dec 21 '22 at 05:42
13

Try

def ceil(n):
    return int(-1 * n // 1 * -1)

def floor(n):
    return int(n // 1)

I used int() to make the values integer. As ceiling and floor are a type of rounding, I thought integer is the appropriate type to return.

The integer division //, goes to the next whole number to the left on the number line. Therefore by using -1, I switch the direction around to get the ceiling, then use another * -1 to return to the original sign. The math is done from left to right.

James Barton
  • 131
  • 1
  • 4
8

I know this is old...but you can call those like this too:

>>> (3/2).__ceil__()
2
>>> (3/2).__floor__()
1

edit: this is for python 3.9 and above

farhan778
  • 81
  • 2
  • 3
  • This is cool, where can I find more information about this? Do all number objects have this dunder function? – user1473249581 May 24 '22 at 00:12
  • All Real instances have this. You can see the numbers.Real docs: [here](https://docs.python.org/3/library/numbers.html#numbers.Real) – farhan778 May 25 '22 at 06:23
5

Try:

def ceil(n):
    res = int(n)
    return res if res == n or n < 0 else res+1

def floor(n):
    res = int(n)
    return res if res == n or n >= 0 else res-1
acw1668
  • 40,144
  • 5
  • 22
  • 34
0

try it like:

if a%b != 0:
  print(int(a//b + 1))
else:
  print(int(a/b))