Генерация равномерно распределенных кратных / выборок в диапазоне

Specific instance of Problem
У меня есть диапазон от 1 до 100. Я хочу сгенерировать n всего чисел в этом диапазоне, которыеas evenly distributed as possible и включите первое и последнее значения.

Example

<code>start = 1, end = 100, n = 5   
Output: [1, 25, 50, 75, 100]

start = 1, end = 100, n = 4   
Output: [1, 33, 66, 100]

start = 1, end = 100, n = 2   
Output: [1, 100]
</code>

What I currently have
У меня на самом деле рабочий подход, но я все еще чувствую, что переборщил с этим и упустил что-то более простое? Это наиболее эффективный подход или его можно улучшить?

<code>def steps(start, end, n):
    n = min(end, max(n, 2) - 1)
    mult = end / float(n)
    yield start
    for scale in xrange(1, n+1):
        val = int(mult * scale)
        if val != start:
            yield val
</code>

Обратите внимание, я гарантирую, что эта функция всегда будет возвращать как минимум нижнее и верхнее предельные значения диапазона. Итак, я заставляюn >= 2

Просто для справки по поиску, я использую это для выборки кадров изображения из отрендеренной последовательности, где вы обычно хотите первый, средний, последний. Но я хотел иметь возможность лучше масштабировать, обрабатывать действительно длинные последовательности изображений и получать лучшее покрытие.

Solved: From the selected answer

В конечном итоге я использовал эту слегка измененную версию ответа @ vartec, чтобы быть генератором, а также ограничилn значение для безопасности:

<code>def steps(start,end,n):
    n = min(end, max(n, 2))
    step = (end-start)/float(n-1)
    return (int(round(start+x*step)) for x in xrange(n))
</code>
 jdi10 апр. 2012 г., 18:01
@vartec: Вы правы, я забыл использоватьround :-)
 bmu10 апр. 2012 г., 11:05
Например, 2 ваши номера не расположены равномерно (см. Мой ответ) или я что-то пропустил?
 jdi10 апр. 2012 г., 18:01
@bmu: Ты ничего не пропустил. Я забыл использоватьround чтобы сделать это еще ближе.
 vartec10 апр. 2012 г., 11:03
[1, 33, 66, 100] это даже не возможно, это должно быть[1, 33, 67, 100]В конце концов, 66.66 (6) следует округлить в большую сторону, а не в меньшую сторону.
 jamylak10 апр. 2012 г., 10:26
Ваш код не обрабатываетсяlist(steps(50,100,3))

Ответы на вопрос(5)

range является то, что шаг должен быть целым числом, и поэтому вы получаете вопросы округления, такие какsteps(1,100,4) == [1, 33, 66, 100], Если вы хотите получить целочисленные выходные данные, но хотите сделать шаг как можно больше, используйте в качестве шага число с плавающей запятой.

>>> def steps(start,end,n):
...    step = (end-start)/float(n-1)
...    return [int(round(start+i*step)) for i in range(n)]

>>> steps(1,100,5)
>>> [1, 26, 51, 75, 100]
>>> steps(1,100,4)
>>> [1, 34, 67, 100]
>>> steps(1,100,2)
>>> [1, 100]
>>>
 10 апр. 2012 г., 18:27
@jdi: это довольно легко проверить, просто наведите курсор мыши'N hours ago', Его редактирование через 10 минут после моего ответа.
 jdi10 апр. 2012 г., 19:32
@vartec: Ах, я сравнивал их неправильно. Смотрел на отметку времени его редактирования против вашего комментария (не ваш ответ против его редактирования).
 10 апр. 2012 г., 20:02
@vartec: Я пропустил ваш ответ, когда вернулся к редактированию. На что ты ссылаешься 33,33?
 jdi10 апр. 2012 г., 18:22
@vartec: Он исправил проблему с округлением до того, как вы прокомментировали? Он сказал, что вы прокомментировали это после того, как он, должно быть, исправил это, и теперь у вас обоих есть идентичные ответы. Я пытался выяснить, у кого это было первым, так как я хотел принять это.
 10 апр. 2012 г., 21:30
@ IainRist: NVM, мой плохой, я считал от 0. Во всяком случае, не имеет значения, вы получили мое одобрение, так как ваш ответ также является правильным.

возможно, излишняя, но короткая, проверенная и должна дать правильные результаты:numpy.linspace

>>> numpy.linspace(1, 100, 4).astype(int).tolist()
[1, 34, 67, 100]
 jdi10 апр. 2012 г., 18:15
Ах, действительно круто! Я хотел ограничить свои зависимости в этом случае, но я проголосовал за это и буду помнить, что это доступно. Спасибо!
Решение Вопроса

def steps(start,end,n):
    if n<2:
        raise Exception("behaviour not defined for n<2")
    step = (end-start)/float(n-1)
    return [int(round(start+x*step)) for x in range(n)]
 04 дек. 2013 г., 16:38
@NathanRossPowell: там
 jdi10 апр. 2012 г., 19:34
Спасибо за упрощение этого. Я упустил из видуround скорее всего, потому что это конкретное приложение не настолько чувствительно, чтобы сказать, 66 против 67, поэтому оно не подняло мне флажок.
 04 дек. 2013 г., 16:09
Сn как1 Вы получаете ошибку деления на ноль.
>>> from itertools import count
>>> def steps(start,end,n):
        yield start
        begin = start if start>1 else 0
        c = count(begin,(end-begin)/(n-1))
        next(c)
        for _ in range(n-2):
            yield next(c)
        yield end


>>> list(steps(1,100,2))
[1, 100]
>>> list(steps(1,100,5))
[1, 25, 50, 75, 100]
>>> list(steps(1,100,4))
[1, 33, 66, 100]
>>> list(steps(50,100,3))
[50, 75, 100]
>>> list(steps(10,100,10))
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

>>> from itertools import islice, count
>>> def steps(start,end,n):
        yield start
        begin = start if start>1 else 0
        c = islice(count(begin,(end-begin)/(n-1)),1,None)
        for _ in range(n-2):
            yield next(c)
        yield end
 jdi10 апр. 2012 г., 09:50
Пока у вас и у @Abhijit есть отличные предложения, но у них обоих есть проблемы сn == 4, Они возвращают 5 результатов, которые не распределены равномерно.
 10 апр. 2012 г., 10:05
У меня новая версия сейчас
 jdi10 апр. 2012 г., 18:19
Спасибо за обновленную версию! Я проголосовал за это, но некоторые люди придумали более короткую версию, которая также исправила мою маленькую оплошность.

спектр? Вот как это можно использовать

>>> def steps(start,end,n):
    return [start]+range(start-1,end,end/(n-1))[1:]+[end]

>>> steps(1,100,5)
[1, 25, 50, 75, 100]
>>> steps(1,100,2)
[1, 100]
>>> 
 10 апр. 2012 г., 09:14
Нет, лучше не ... это вызывает путаницу. +1 к слову
 10 апр. 2012 г., 09:12
Ух ты, у меня был точно такой же код, как и у тебя ... состояние гонки ...: D
 10 апр. 2012 г., 11:10
Извините, это просто не численно стабильно. У вас проблемы с ошибками округления:steps(1,100,15) - & GT;[1, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98, 100]
 10 апр. 2012 г., 09:13
:-) Ну, вы могли бы опубликовать это. По крайней мере, люди будут понимать, основываясь на разнице во времени
 jdi10 апр. 2012 г., 09:48
Мне действительно нравится, где это происходит, но это имеет проблему, когдаn == 4 по сравнению с тем, как мой справляется с этим. Та же проблема с ответом от @jamylak

Ваш ответ на вопрос