I would not necessarily consider this more Pythonic, but if you'd like to avoid invoking the math.floor
and math.ceiling
functions and are looking for something more algebraic, you could do something like this:
def away_from_zero(x):
return int(x // 1 + 2 ** (x > 0) - 1)
As an explanation:
The integer division x // 1
will round down any floating point number, negative or positive, to the nearest integer that's less than x
. So 1.5
goes to 1.0
and -1.5
goes to -2.0
. This alone solves the problem for negative values and whole numbers, but positive non-integers are off-by-one.
To account for the positive case, we want to offset the result by 1
when x
is positive but not when it's negative. You could use conditional logic for this, but if you want to restrict the computation to a single equation, you could also add some term that equals 1
when x
is positive and 0
when x
is negative. To that end, we have 2 ** (x > 0) - 1
. Here, when x
is positive, we have
>>> 2 ** True - 1
1
When x
is negative, we have
>>> 2 ** False - 1
0
Finally, since integer division of a float
returns a float
, we cast the result to an int
, which gives the desired behavior:
>>> away_from_zero(1.4)
2
>>> away_from_zero(1.6)
2
>>> away_from_zero(-1.4)
-2
>>> away_from_zero(-1.6)
-2