how to efficiently create a range of float numbers

234 views Asked by At

Suppose I want to create a set of float numbers starting from 0.1 to 0.00001 as first diving by two and then diving by 5. In other words, I'd like to get the numbers shown below.

0.1
0.05
0.01
0.005
0.001
0.0005
0.0001
0.00005
0.00001

For this small example, I wrote the following code snippet which works fine.

import numpy as np
def format_float(num):
    return np.format_float_positional(num, trim='-')

num = 0.1

for j in range(9):
    if j ==0:
        rate=np.round(num*(0.1),j+1)
        print(format_float(num))
    elif ( (j+1) % 2) != 0:
        num=np.round(num*(0.2),j+1)
        print(format_float(num))
    else:
        num =np.round(num/2,j+1)
        print(format_float(num))

My question is if there is a more elegant way to perform this operation given different rules. For instance, suppose I would like to get the number between x and y where the rule is to first divide by k and then divide by l in order. I believe this should be managable through linspace, but I could not do it.

3

There are 3 answers

0
ddejohn On BEST ANSWER
In [1]: import numpy as np

In [2]: np.repeat(1 / 10**np.arange(1, 5), 2)[1:] * np.array([1., 5.]*4)[:-1]
Out[2]: array([0.1   , 0.05  , 0.01  , 0.005 , 0.001 , 0.0005, 0.0001])

Generalizing for any "pattern":

def rates(smallest_magnitude, pattern):
    n = len(pattern)
    pows = np.repeat(1 / 10**np.arange(1, smallest_magnitude), n)[(n-1):]
    mults = np.array(pattern * (smallest_magnitude - 1))[:-(n-1)]
    return np.round(pows * mults, smallest_magnitude)

Demo:

In [4]: print(*rates(5, [1, 5]))  # Your original 'pattern'
0.1 0.05 0.01 0.005 0.001 0.0005 0.0001

In [5]: print(*rates(5, [2, 4, 8]))
0.2 0.04 0.08 0.02 0.004 0.008 0.002 0.0004 0.0008 0.0002

In [6]: print(*rates(5, [3, 5, 7, 9]))
0.3 0.05 0.07 0.09 0.03 0.005 0.007 0.009 0.003 0.0005 0.0007 0.0009 0.0003
4
Tim Roberts On

This works, but I'm not sure it's any better than your method.

import numpy as np

# Create the powers of ten:
a = 0.1 ** np.arange(1,6)
# Interleave the halves in between:
a = np.concatenate((a,a/2))
# Sort and reverse: 
a.sort()
a = a[-1::-1]

print(a)
2
no comment On

Two ways:

>>> np.cumprod([.1] + 4*[1/2, 1/5])
array([1.e-01, 5.e-02, 1.e-02, 5.e-03, 1.e-03, 5.e-04, 1.e-04, 5.e-05,
       1.e-05])
>>> 1 / np.cumprod([10] + 4*[2, 5])
array([1.e-01, 5.e-02, 1.e-02, 5.e-03, 1.e-03, 5.e-04, 1.e-04, 5.e-05,
       1.e-05])