Предположим, я хочу создать набор чисел с плавающей запятой, начиная с 0,1 до 0,00001, сначала погружаясь на два, а затем на 5. Другими словами, я хотел бы получить числа, показанные ниже.

0.1
0.05
0.01
0.005
0.001
0.0005
0.0001
0.00005
0.00001

Для этого небольшого примера я написал следующий фрагмент кода, который отлично работает.

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))

Мой вопрос в том, есть ли более элегантный способ выполнить эту операцию с учетом других правил. Например, предположим, что я хотел бы получить число между x и y, где правило состоит в том, чтобы сначала разделить на k, а затем по порядку разделить на l. Я считаю, что это можно сделать через linspace, но я не мог этого сделать.

3
whitepanda 11 Окт 2021 в 20:42

3 ответа

Лучший ответ
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])

Обобщение для любого «паттерна»:

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)

Демо:

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
2
ddejohn 11 Окт 2021 в 18:48

Это работает, но я не уверен, что это лучше вашего метода.

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)
1
Tim Roberts 11 Окт 2021 в 18:18

Два пути:

>>> 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])
1
don't talk just code 11 Окт 2021 в 18:39