np.ceil in python doesn't work in for loop - python

I am quite new to python and I have a problem with the np.ceil function. So when I do np.ceil(10/0.1), I get 100, which is what I expect. However when I do it in a for loop:
interval = np.arange(0.01,0.2,0.01)
for i in interval:
print(np.ceil(10/i))
I obtain the right results for all values of i, except for i=0.1. For this I get 101 instead of 100. Can someone tell me why is this happening? Thank you!

It has nothing to do with being in a variable or not. The values are simply not the same:
In [9]: interval
Out[9]:
array([ 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09,
0.1 , 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19])
In [10]: x = interval[9]
In [11]: x
Out[11]: 0.099999999999999992
In [12]: i = 0.1
In [13]: x == i
Out[13]: False
Note, neither number is exactly 0.1 since that number cannot be represented exactly using binary floating point. Also note:
In [14]: type(x), type(i)
Out[14]: (numpy.float64, float)
Although, that isn't as relevant.

You can force another float representation by rounding it.
This should do the trick in your specific case.
interval = np.arange(0.01,0.2,0.01)
for i in interval:
if i == 0.1:
print('this will miss')
if i == interval[9]:
print('this will hit')
j = round(i, 3)
print(np.ceil(10/i), np.ceil(10/j))

Related

How can I reduce time complexity on this algorithm?

I have this exercise and the goal is to solve it with complexity less than O(n^2).
You have an array with length N filled with event probabilities. Create another array in which for each element i calculate the probability of all event to happen until the position i.
I have coded this O(n^2) solution. Any ideas how to improve it?
probabilityTable = [0.1, 0.54, 0.34, 0.11, 0.55, 0.75, 0.01, 0.06, 0.96]
finalTable = list()
for i in range(len(probabilityTable)):
finalTable.append(1)
for j in range(i):
finalTable[i] *= probabilityTable[j]
for item in finalTable:
print(item)
probabilityTable = [0.1, 0.54, 0.34, 0.11, 0.55, 0.75, 0.01, 0.06, 0.96]
finalTable = probabilityTable.copy()
for i in range(1, len(probabilityTable)):
finalTable[i] = finalTable[i] * finalTable[i - 1]
for item in finalTable:
print(item)
new_probs = [probabilityTable[0]]
for prob in probabilityTable[1:]:
new_probs.append(new_probs[-1] + prob)

np.arange producing elements with many decimals

I have the following loop.
x_array = []
for x in np.arange(0.01, 0.1, 0.01 ):
x_array.append(x)
Why are some of the elements in x_array in so many decimals?
[0.01,
0.02,
0.03,
0.04,
0.05,
0.060000000000000005,
0.06999999999999999,
0.08,
0.09]
If you want your list of numbers without "additional" digits in the
fractional part, try the following code:
x_array = np.arange(0.01, 0.1, 0.01).round(2).tolist()
As you see, you don't even need any explicit loop.
The result is just what you want, i.e.:
[0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09]
Another choice is:
x_array = (np.arange(1, 10) / 100).tolist()

How to get elements from a specific range out of a list?

Does anybody have an idea how to get the elements in a list whose values fall within a specific (from - to) range?
I need a loop to check if a list contains elements in a specific range, and if there are any, I need the biggest one to be saved in a variable..
Example:
list = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
# range (0.5 - 0.58)
# biggest = 0.56
You could use a filtered comprehension to get only those elements in the range you want, then find the biggest of them using the built-in max():
lst = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
biggest = max([e for e in lst if 0.5 < e < 0.58])
# biggest = 0.56
As an alternative to other answers, you can also use filter and lambda:
lst = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
biggest = max([i for i in filter(lambda x: 0.5 < x < 0.58, lst)])
I suppose a normal if check would be faster, but I'll give this just for completeness.
Also, you should not use list = ... as list is a built-in in python.
You could also go about it a step at a time, as the approach may aid in debugging.
I used numpy in this case, which is also a helpful tool to put in your tool belt.
This should run as is:
import numpy as np
l = [0.5, 0.56, 0.34, 0.45, 0.53, 0.6]
a = np.array(l)
low = 0.5
high = 0.58
index_low = (a < high)
print(index_low)
a_low = a[index_low]
print(a_low)
index_in_range = (a_low >= low)
print(index_in_range)
a_in_range = a_low[index_in_range]
print(a_in_range)
a_max = a_in_range.max()
print(a_max)

Find index of the first value that is below/above a threshold

I have a list with a series of random floats that go from negative to positive, like:
values = [0.001, 0.05, 0.09, 0.1, 0.4, 0.8, 0.9, 0.95, 0.99]
I wish to filter out the indices that first meet the greater than/less than values that I wish. For example, if I want the first closest value less than 0.1 I would get an index of 2 and if I want the first highest value greater than 0.9 I'd get 7.
I have a find_nearest method that I am using but since this dataset is randomized, this is not ideal.
EDIT: Figured out a solution.
low = next(x[0] for x in enumerate(list(reversed(values))) if x[1] < 0.1)
high = next(x[0] for x in enumerate(values) if x[1] > 0.9)
if the values list gets long you may want the bisect module from the standard lib
bisect_left, bisect_right may serve as the >, < tests
import bisect
values = [0.001, 0.05, 0.09, 0.1, 0.4, 0.8, 0.9, 0.95, 0.99]
bisect.bisect_left(values, .1)
Out[226]: 3
bisect.bisect_right(values, .1)
Out[227]: 4

Python for loop with small steps [duplicate]

This question already has answers here:
How do I use a decimal step value for range()?
(34 answers)
Closed 9 years ago.
How can I make an for loop in python with steps of 0.01?
I tried this but it doesn't work:
for X0 in range (-0.02, 0.02, 0.01):
for Y0 in range (-0.06, 0.09, 0.01):
it says
TypeError: range() integer end argument expected, got float.
[x * 0.01 for x in xrange(10)]
will produce
[0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09]
The python range only takes integers as the error message indicates. If you want to use float steps, you can either use numpy's arange or just divide a integer range:
>>> import numpy as np
>>> print np.arange(-0.02, 0.02, 0.01)
array([-0.02, -0.01, 0. , 0.01])
in your example:
for X0 in np.arange(-0.02, 0.02, 0.01):
for Y0 in np.arange(-0.06, 0.09, 0.01):
or:
>>> print [a/0.01 - 0.02 for a in range(4)]
[-0.02, -0.01, 0.0, 0.009999999999999998]
If you don't want to use a library:
def float_range(a,b,c):
while a < b:
yield a
a += c
for X0 in float_range (-0.02, 0.02, 0.01):
for Y0 in float_range (-0.06, 0.09, 0.01):
print X0, Y0

Categories