Вычисление диапазона точного количества значений в Python - PullRequest
4 голосов
/ 18 марта 2010

Я строю диапазон между двумя числами (числами с плавающей запятой), и я хотел бы, чтобы этот диапазон был точно фиксированной длины (не больше, не меньше) range и arange вместо этого работают с шагами. Чтобы поместить вещи в псевдо-Python, я бы хотел достичь этого:

start_value = -7.5
end_value = 0.1
my_range = my_range_function(star_value, end_value, length=6)

print my_range
[-7.50,-5.98,-4.46,-2.94,-1.42,0.10]

Это, по сути, эквивалентно функции R seq, которая может указывать последовательность заданной длины. Возможно ли это в Python?

Спасибо.

Ответы [ 5 ]

6 голосов
/ 18 марта 2010

Используйте linspace () из NumPy .

>>> from numpy import linspace
>>> linspace(-7.5, 0.1, 6)
array([-7.5 , -5.98, -4.46, -2.94, -1.42,  0.1])
>>> linspace(-7.5, 0.1, 6).tolist()
[-7.5, -5.9800000000000004, -4.46, -2.9399999999999995, -1.4199999999999999, 0.10000000000000001]

Это должно быть наиболее эффективным и точным.

4 голосов
/ 18 марта 2010

См. Рецепт 66472: frange (), функция диапазона с приращениями с плавающей точкой (Python) с различными реализациями с плавающей точкой, их плюсы и минусы.

В качестве альтернативы, если для вас важна точность, используйте decimal.Decimal вместо числа с плавающей запятой (преобразование в и затем обратно), как указано в Значение шага десятичного диапазона Python () .

2 голосов
/ 18 марта 2010
def my_function(start, end, length):
    len = length - 1
    incr = (end-start) / len
    r = [ start ]
    for i in range(len):
        r.append ( r[i] + incr )
    return r
1 голос
/ 18 марта 2010

Для обработки ошибок округления в следующем коде используется десятичный модуль Python . Вы можете установить округление; для этого примера я установил его до двух десятичных точек через round_setting = '.01'. Для обработки любых ошибок округления последний шаг корректируется до остатка.

код

#!/usr/bin/env python
# encoding: utf-8
from __future__ import print_function
import math
import decimal


start_value = -7.5
end_value = 0.1
num_of_steps = 6

def my_range(start_value, end_value, num_of_steps):
    round_setting = '.01'
    start_decimal = decimal.Decimal(str(start_value)).quantize(
        decimal.Decimal(round_setting))
    end_decimal = decimal.Decimal(str(end_value)).quantize(
        decimal.Decimal(round_setting))
    num_of_steps_decimal = decimal.Decimal(str(num_of_steps)).quantize(
        decimal.Decimal(round_setting))
    step_decimal = ((end_decimal - start_decimal) / 
        num_of_steps_decimal).quantize(decimal.Decimal(round_setting))
    # Change the last step in case there are rounding errors
    last_step_decimal = (end_decimal - ((num_of_steps - 1) * step_decimal) -
            start_decimal).quantize(decimal.Decimal(round_setting))
    print('Start value = ', start_decimal)
    print('End value = ', end_decimal)
    print('Number of steps = ', num_of_steps)
    print('Normal step for range = ', step_decimal)
    print('Last step used for range = ', last_step_decimal)

my_range(start_value, end_value, num_of_steps)

выход

$ ./fixed_range.py 
Start value =  -7.50
End value =  0.10
Number of steps =  6
Normal step for range =  1.27
Last step used for range =  1.25

Оттуда вы можете использовать обычный шаг и последний шаг, чтобы создать свой список.

1 голос
/ 18 марта 2010

Как насчет этого:

def my_range_function(start, end, length):
    if length <= 1: return [ start ]
    step = (end - start) / (length - 1)
    return [(start + i * step) for i in xrange(length)]

Для вашего диапазона выборки возвращается:

[-7.5, -5.9800000000000004, -4.46,
 -2.9399999999999995, -1.4199999999999999, 0.099999999999999645]

Конечно, он полон круглых ошибок, но это то, что вы получаете, работая с плавающей точкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...