I have found two ways of taking floors in Python:
3.1415 // 1
and
import math
math.floor(3.1415)
The problem with the first approach is that it return a float (namely 3.0). The second approach feels clumsy and too long.
Are there alternative solutions for taking floors in Python?
As long as your numbers are positive, you can simply convert to an int to round down to the next integer:
>>> int(3.1415)
3
For negative integers, this will round up, though.
You can call int() on the float to cast to the lower int (not obviously the floor but more elegant)
int(3.745) #3
Alternatively call int on the floor result.
from math import floor
f1 = 3.1415
f2 = 3.7415
print floor(f1) # 3.0
print int(floor(f1)) # 3
print int(f1) # 3
print int(f2) # 3 (some people may expect 4 here)
print int(floor(f2)) # 3
http://docs.python.org/library/functions.html#int
The second approach is the way to go, but there's a way to shorten it.
from math import floor
floor(3.1415)
Beware that taking the floor and casting to an int are not the same thing with negative numbers. If you really want the floor as an integer, you should cast to an int after calling math.floor().
>>> int(-0.5)
0
>>> math.floor(-0.5)
-1.0
>>> int(math.floor(-0.5))
-1
Cast it to int if you don't want a float
int(3.1415 // 1)
from math import floor
def ff(num, step=0):
if not step:
return floor(num)
if step < 0:
mplr = 10 ** (step * -1)
return floor(num / mplr) * mplr
ncnt = step
if 1 > step > 0:
ndec, ncnt = .0101, 1
while ndec > step:
ndec *= .1
ncnt += 1
mplr = 10 ** ncnt
return round(floor(num * mplr) / mplr, ncnt)
You can use positive/negative numbers and float points .1, .01, .001...
Related
I would like to design a function f(x : float, up : bool) with these input/output:
# 2 decimals part rounded up (up = True)
f(142.452, True) = 142.46
f(142.449, True) = 142.45
# 2 decimals part rounded down (up = False)
f(142.452, False) = 142.45
f(142.449, False) = 142.44
Now, I know about Python's round built-in function but it will always round 142.449 up, which is not what I want.
Is there a way to do this in a nicer pythonic way than to do a bunch of float comparisons with epsilons (prone to errors)?
Have you considered a mathematical approach using floor and ceil?
If you always want to round to 2 digits, then you could premultiply the number to be rounded by 100, then perform the rounding to the nearest integer and then divide again by 100.
from math import floor, ceil
def rounder(num, up=True):
digits = 2
mul = 10**digits
if up:
return ceil(num * mul)/mul
else:
return floor(num*mul)/mul
You can also perform some mathematical logic if you do not want to use any explicit function as:
def f(num, up):
num = num * 100
if up and num != int(num): # if up and "float' value != 'int' value
num += 1
return int(num) / (100.0)
Here, the idea is if up is True and int value of number is not equal to float value then increase the number by 1. Else it will be same as the original number
math.ceil() rounds up, and math.floor() rounds down. So, the following is an example of how to use it:
import math
def f(x, b):
if b:
return (math.ceil(100*x) / 100)
else:
return (math.floor(100*x) / 100)
This function should do exactly what you want.
Could someone help check why the result is always one and let me know what I did wrong? Thanks
Correct result should be: 1/1 + 1/2 + 1/3 == 1.83333333333.
x = int(input("Enter n: "))
assert x > 0, "n must be greater than zero!"
def one_over_n(x):
result = 0
for n in range(x):
n += 1
result += 1 / n
return result
r = one_over_n(x)
print("one_over_n( {0:d} ): {1:f}" .format(x, r))
It will work correctly on python 3, but not in python 2
>>> 1/2
0
That means you are just adding zeroes, to one. You will need to change either numerator or denominator to a float number e.g. 1/2.0, so change your code to
result += 1.0 / n
See Pep 238 to see why it was changed in python 3.
btw floating point numbers can't represent all fractions, so if you are just adding fractions, you can use Fraction class e.g.
>>> from fractions import Fraction as F
>>> F(1,1) + F(1,2) + F(1,3)
Fraction(11, 6)
As an alternative, to force Python 2 perform division as you expect (rather than integer division), add:
from __future__ import division
1/2
gives
0
as it should. However,
-1/2
gives
-1
, but I want it to round towards 0 (i.e. I want -1/2 to be 0), regardless of whether it's positive or negative. What is the best way to do that?
Do floating point division then convert to an int. No extra modules needed.
Python 3:
>>> int(-1 / 2)
0
>>> int(-3 / 2)
-1
>>> int(1 / 2)
0
>>> int(3 / 2)
1
Python 2:
>>> int(float(-1) / 2)
0
>>> int(float(-3) / 2)
-1
>>> int(float(1) / 2)
0
>>> int(float(3) / 2)
1
Python's default division of integers is return the floor (towards negative infinity) with no ability to change that. You can read the BDFL's reason why.
To do 'round up' division, you would use:
>>> a=1
>>> b=2
>>> (a+(-a%b))//b
1
>>> a,b=-1,2
>>> (a+(-a%b))//b
0
To do truncation towards zero, and maintain integer division, you use (a+(-a%b))//b if either a or b are negative and the default division if both are positive.
This will do integer division and always round towards zero:
>>> a=1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a=-1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a,b=-3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
-1
>>> a,b=3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
1
footnote
Interestingly enough, C99 declares that round towards zero is the default:
#include <stdio.h>
int main(int argc, const char * argv[])
{
int a=-3;
int b=2;
printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
a=3;
printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
return 0;
}
Prints:
a=-3, b=2, a/b=-1
a=3, b=2, a/b=1
For what it's worth, my own favourite solution is this one. Integer arithmetic only, a single division, and everything else linear time:
def integer_divide_towards_zero(a, b):
return -(-a // b) if a < 0 else a // b
That assumes that b is positive, but in most of the applications I've seen that's true. If you need to deal with negative b too, then the function becomes marginally more complicated:
def integer_divide_towards_zero(a, b):
return -(-a // b) if (a < 0) ^ (b < 0) else a // b
Some sample outputs:
>>> integer_divide_towards_zero(11, 3)
3
>>> integer_divide_towards_zero(-11, 3)
-3
>>> integer_divide_towards_zero(6, 3)
2
>>> integer_divide_towards_zero(-6, 3)
-2
>>> integer_divide_towards_zero(11, -3)
-3
>>> integer_divide_towards_zero(-11, -3)
3
why reinvent the wheel, when there's a perfectly good math.trunc() function?
import math
print(math.trunc(-3.5))
>>-3
print(math.trunc(3.5))
>>3
Try this. Only works for numbers greater than -1
import math
x = .5
y = -.5
print math.floor(math.fabs(x))
>> 0
print math.floor(math.fabs(y))
>> 0
Correct code to do this is, in my opinion, too obscure to write as a 1-liner. So I'd put it in a function, like:
def int0div(a, b):
q = a // b
if q < 0 and b*q != a:
q += 1
return q
Good features: it works for any size of int, doesn't make any adjustment to the raw (a//b) result unless necessary, only does one division (% also does a division under the covers), and doesn't create any integers larger than the inputs. Those may or may not matter in your application; they become more important (for speed) if you use "big" integers.
Throwing my hat in with a few alternate ideas:
Multiple the sign of the number [abs(x)/x] by the abs(x)/2
(abs(x)/x)*(abs(x)/2)
Perform the addition, but if the number is less than zero add one to shift it closer to 0.
x/2 + int(x<0)
You can also use the Decimal module as part of the standard python libraries.
Specifically,
" The integer division operator // behaves analogously, returning the integer part of the true quotient (truncating towards zero) rather than its floor, so as to preserve the usual identity x == (x // y) * y + x % y:"
>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')
Also, have a look at Rounding Modes as they've got quite a few ways to view/round your information - Ceiling, down, floor, half-down, half-even, half-up, up and 05up rounding.
Decimal was written as a solution to the traditional problem of binary mathematics in a world expecting decimals solutions
Is there a standard library function which will set a minimum value to a division operation, for example:
min(1, a/b)
This will ensure that min value of operation above will always be 1, never 0.
Such as:
min(1, 1/5)
1
Also, how do I round up a division:
round_up(1/5) = 1
I always get "0" when I divide 1/5, even with ceil function:
math.ceil(1/5)
0
If you want to use floating point division as default, you can do from __future__ import division:
>>> 1/5
0
>>> from __future__ import division
>>> 1/5
0.2
>>> math.ceil(1/5)
1.0
If you need the result to be of integer type, e.g. for indexing, you can use
int(math.ceil(1/5))
The result of 1/5 is an integer already. If you want the floating point version you need to do 1.0/5. The math.ceil function will then work as you expect: math.ceil(1.0/5) = 1.0.
If you're working with variables instead of constants, use the float(x) function to convert an integer into a floating point.
In [4]: 1/5
Out[4]: 0
In [5]: math.ceil(1/5)
Out[5]: 0.0
In [7]: float(1)/5
Out[7]: 0.2
In [8]: math.ceil(float(1)/5)
Out[8]: 1.0
You could make a round up function for integers like this
>>> def round_up(p, q):
... d, r = divmod(p, q)
... if r != 0:
... d += 1
... return d
...
>>> round_up(1, 5)
1
>>> round_up(0, 5)
0
>>> round_up(5, 5)
1
>>> round_up(6, 5)
2
>>>
Your example doesn't work because an integer dividing an integer is an integer.
As for your min question - what you wrote is probably the best you can do.
I don't know about anything in the standard library, but if you are just trying to make sure the answer is never less than 1, the function is pretty easy:
def min_dev(x,y):
ans = x/y
if ans < 1: # ensures answer cannot be 0
return 1
else: # answers greater than 1 are returned normally
return ans
If, instead, you are looking to round up every answer:
def round_up(x,y):
ans = x//y # // is the floor division operator
if x % y == 1: # tests for remainder (returns 0 for no, 1 for yes)
ans += 1 # same as ans = ans + 1
return ans
else:
return ans
This will round up any answer with a remainder.
I believe Python 3.3 (and I know 3.4) return a float by default for integer division: https://docs.python.org/3/tutorial/introduction.html
In Python 3, I am checking whether a given value is triangular, that is, it can be represented as n * (n + 1) / 2 for some positive integer n.
Can I just write:
import math
def is_triangular1(x):
num = (1 / 2) * (math.sqrt(8 * x + 1) - 1)
return int(num) == num
Or do I need to do check within a tolerance instead?
epsilon = 0.000000000001
def is_triangular2(x):
num = (1 / 2) * (math.sqrt(8 * x + 1) - 1)
return abs(int(num) - num) < epsilon
I checked that both of the functions return same results for x up to 1,000,000. But I am not sure if generally speaking int(x) == x will always correctly determine whether a number is integer, because of the cases when for example 5 is represented as 4.99999999999997 etc.
As far as I know, the second way is the correct one if I do it in C, but I am not sure about Python 3.
There is is_integer function in python float type:
>>> float(1.0).is_integer()
True
>>> float(1.001).is_integer()
False
>>>
Both your implementations have problems. It actually can happen that you end up with something like 4.999999999999997, so using int() is not an option.
I'd go for a completely different approach: First assume that your number is triangular, and compute what n would be in that case. In that first step, you can round generously, since it's only necessary to get the result right if the number actually is triangular. Next, compute n * (n + 1) / 2 for this n, and compare the result to x. Now, you are comparing two integers, so there are no inaccuracies left.
The computation of n can be simplified by expanding
(1/2) * (math.sqrt(8*x+1)-1) = math.sqrt(2 * x + 0.25) - 0.5
and utilizing that
round(y - 0.5) = int(y)
for positive y.
def is_triangular(x):
n = int(math.sqrt(2 * x))
return x == n * (n + 1) / 2
You'll want to do the latter. In Programming in Python 3 the following example is given as the most accurate way to compare
def equal_float(a, b):
#return abs(a - b) <= sys.float_info.epsilon
return abs(a - b) <= chosen_value #see edit below for more info
Also, since epsilon is the "smallest difference the machine can distinguish between two floating-point numbers", you'll want to use <= in your function.
Edit: After reading the comments below I have looked back at the book and it specifically says "Here is a simple function for comparing floats for equality to the limit of the machines accuracy". I believe this was just an example for comparing floats to extreme precision but the fact that error is introduced with many float calculations this should rarely if ever be used. I characterized it as the "most accurate" way to compare in my answer, which in some sense is true, but rarely what is intended when comparing floats or integers to floats. Choosing a value (ex: 0.00000000001) based on the "problem domain" of the function instead of using sys.float_info.epsilon is the correct approach.
Thanks to S.Lott and Sven Marnach for their corrections, and I apologize if I led anyone down the wrong path.
Python does have a Decimal class (in the decimal module), which you could use to avoid the imprecision of floats.
floats can exactly represent all integers in their range - floating-point equality is only tricky if you care about the bit after the point. So, as long as all of the calculations in your formula return whole numbers for the cases you're interested in, int(num) == num is perfectly safe.
So, we need to prove that for any triangular number, every piece of maths you do can be done with integer arithmetic (and anything coming out as a non-integer must imply that x is not triangular):
To start with, we can assume that x must be an integer - this is required in the definition of 'triangular number'.
This being the case, 8*x + 1 will also be an integer, since the integers are closed under + and * .
math.sqrt() returns float; but if x is triangular, then the square root will be a whole number - ie, again exactly represented.
So, for all x that should return true in your functions, int(num) == num will be true, and so your istriangular1 will always work. The only sticking point, as mentioned in the comments to the question, is that Python 2 by default does integer division in the same way as C - int/int => int, truncating if the result can't be represented exactly as an int. So, 1/2 == 0. This is fixed in Python 3, or by having the line
from __future__ import division
near the top of your code.
I think the module decimal is what you need
You can round your number to e.g. 14 decimal places or less:
>>> round(4.999999999999997, 14)
5.0
PS: double precision is about 15 decimal places
It is hard to argue with standards.
In C99 and POSIX, the standard for rounding a float to an int is defined by nearbyint() The important concept is the direction of rounding and the locale specific rounding convention.
Assuming the convention is common rounding, this is the same as the C99 convention in Python:
#!/usr/bin/python
import math
infinity = math.ldexp(1.0, 1023) * 2
def nearbyint(x):
"""returns the nearest int as the C99 standard would"""
# handle NaN
if x!=x:
return x
if x >= infinity:
return infinity
if x <= -infinity:
return -infinity
if x==0.0:
return x
return math.floor(x + 0.5)
If you want more control over rounding, consider using the Decimal module and choose the rounding convention you wish to employ. You may want to use Banker's Rounding for example.
Once you have decided on the convention, round to an int and compare to the other int.
Consider using NumPy, they take care of everything under the hood.
import numpy as np
result_bool = np.isclose(float1, float2)
Python has unlimited integer precision, but only 53 bits of float precision. When you square a number, you double the number of bits it requires. This means that the ULP of the original number is (approximately) twice the ULP of the square root.
You start running into issues with numbers around 50 bits or so, because the difference between the fractional representation of an irrational root and the nearest integer can be smaller than the ULP. Even in this case, checking if you are within tolerance will do more harm than good (by increasing the number of false positives).
For example:
>>> x = (1 << 26) - 1
>>> (math.sqrt(x**2)).is_integer()
True
>>> (math.sqrt(x**2 + 1)).is_integer()
False
>>> (math.sqrt(x**2 - 1)).is_integer()
False
>>> y = (1 << 27) - 1
>>> (math.sqrt(y**2)).is_integer()
True
>>> (math.sqrt(y**2 + 1)).is_integer()
True
>>> (math.sqrt(y**2 - 1)).is_integer()
True
>>> (math.sqrt(y**2 + 2)).is_integer()
False
>>> (math.sqrt(y**2 - 2)).is_integer()
True
>>> (math.sqrt(y**2 - 3)).is_integer()
False
You can therefore rework the formulation of your problem slightly. If an integer x is a triangular number, there exists an integer n such that x = n * (n + 1) // 2. The resulting quadratic is n**2 + n - 2 * x = 0. All you need to know is if the discriminant 1 + 8 * x is a perfect square. You can compute the integer square root of an integer using math.isqrt starting with python 3.8. Prior to that, you could use one of the algorithms from Wikipedia, implemented on SO here.
You can therefore stay entirely in python's infinite-precision integer domain with the following one-liner:
def is_triangular(x):
return math.isqrt(k := 8 * x + 1)**2 == k
Now you can do something like this:
>>> x = 58686775177009424410876674976531835606028390913650409380075
>>> math.isqrt(k := 8 * x + 1)**2 == k
True
>>> math.isqrt(k := 8 * (x + 1) + 1)**2 == k
False
>>> math.sqrt(k := 8 * x + 1)**2 == k
False
The first result is correct: x in this example is a triangular number computed with n = 342598234604352345342958762349.
Python still uses the same floating point representation and operations C does, so the second one is the correct way.
Under the hood, Python's float type is a C double.
The most robust way would be to get the nearest integer to num, then test if that integers satisfies the property you're after:
import math
def is_triangular1(x):
num = (1/2) * (math.sqrt(8*x+1)-1 )
inum = int(round(num))
return inum*(inum+1) == 2*x # This line uses only integer arithmetic