Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Равномерно распределить числа по интервалу.


Автор: sergejzr 2.5.2007, 01:27
Допустим есть рабочий интервал 0-10000 
Теперь существует множество интервальчиков (примеры: 10-25, 5-500,2000-2003) и всех их надо "растянуть" на рабочий.
http://img339.imageshack.us/my.php?image=overviewpl4.png


Первое что пришло в голову - проекция. Она работает достаточно неплохо, но два нюанса есть. 
http://img261.imageshack.us/my.php?image=projectionqb5.png

1) По краям элементы расходятся быстрее чем в середине
2) Интервалы - это на самом деле примеры по которым предсказываем реальные данные. Это означает, что числа могут выходить за пределы примеров и проекция пошлёт их далеко за пределы рабочего т.к. по краям расхожесть большая (см. пункт 1) 
http://img127.imageshack.us/my.php?image=realvalueqf4.png

Если представить интервалы как резинки, как можно наидудобнее растянуть их на одну длину? Или всё таки проекция не так уж и плоха?

Автор: Artemios 2.5.2007, 12:34
А если тупое линейное сжатие/растяжение пространства?
(то есть элеметнарное масштабирование) плюс смещение...

Автор: kulibinka 2.5.2007, 22:31
Для похожей задачи пользовалася следующим кодом на питоне:
Код

def normalize_list (lst, y0, y1, x0_x1 = ()):
    """ф-я нормализации списка из целых значений
    получаем список целых значений, и нормализуем его значениями от, до
    если есть x0_x1 (а это глобальный минимум-максимум получаемого списка), то мы берем их как минимум-максимум, а иначе в лоб его ищем"""
    rezult = []
    if len(x0_x1)>0:
        x0, x1 = x0_x1
    else:
        x0 = min(lst)
        x1 = max(lst)
    koef = float((y1-y0))/(x1-x0)
    for i in lst:
        rezult.append( float(i-x0)*koef + y0)
    return rezult

Автор: sergejzr 2.5.2007, 23:01
kulibinka,  огромнейшее спасибо! то, что нужно! smile smile 


Автор: Artemios 2.5.2007, 23:54
Цитата(kulibinka @  2.5.2007,  23:31 Найти цитируемый пост)
*koef

растяжение
Цитата(kulibinka @  2.5.2007,  23:31 Найти цитируемый пост)
 + y0

смещение.
 smile 

Автор: sergejzr 3.5.2007, 00:14
Да, это то же самое. И проекция так же. Всё замечательно, но края расходятся довольно круто. Как бы их о буздать?...

Пример растягиваем числа 300-320 на интервал 0-5000 получается коеффициент 250.
если вдруг придёт число 321, то займёт значение уже 5250, а 299 будет уже -250.
А это почти полный исходный интервал! и 5% от общего!

Надо бы проекцию, но не прямыми, а изогнутыми чтобы в заданном интервале было всё нормально, а значения-аутсайдеры не улетали далеко.

Автор: sergejzr 3.5.2007, 00:32
Вот к примеру как на картинке... Прямая отправит аутсайдера в космос, а кривая не даст далеко уйти. Только как это просто сделать....
http://img371.imageshack.us/my.php?image=projectioncurvevx6.pngая

Автор: Artemios 3.5.2007, 01:11
Цитата(sergejzr @  3.5.2007,  01:14 Найти цитируемый пост)
И проекция так же.

Неа, проекция из твоих верхних картинок не является линейным преобразованием, ибо там изометрическая проекция.
Если объяснять "на пальцах" то пусть d -- малый отрезок и D -- большой. При изометрической проекции равным подъинтервалам на d будут соответствовать неравные подъинтервалы на D. При линейном преобразовании (как у kulibinka) -- равным соответствуют равные, и в принципе 5% от общего -- это то же самое, как и 321-320=1 для интервала 320-300=20. 

Если тебе неважно сохранение пропорций, попробуй обратную изометрию. Например, малый отрезок d выгни по дуге окружности с центром в точке, откуда ведёшь проекционные лучи. Только для каждого малого интервала придется подбирать свой радиус и расстояние от центра до D (это уж на твой вкус, пока "разлет" не будет тебя удовлетворять).

Добавлено через 3 минуты и 22 секунды
P.S. И лучи неизвестными кривыми не придется заменять.

Автор: sergejzr 3.5.2007, 01:22
Artemios, хорошая идея... можно попытаться..


Цитата(Artemios @  3.5.2007,  00:11 Найти цитируемый пост)
Если тебе неважно сохранение пропорций,

Не важно, важно только, что порядок точек сверху вниз не нарушится.

Автор: Artemios 3.5.2007, 22:47
Цитата(Artemios @  3.5.2007,  02:11 Найти цитируемый пост)
Если тебе неважно сохранение пропорций, попробуй обратную изометрию. Например, малый отрезок d выгни по дуге окружности с центром в точке, откуда ведёшь проекционные лучи. Только для каждого малого интервала придется подбирать свой радиус и расстояние от центра до D (это уж на твой вкус, пока "разлет" не будет тебя удовлетворять).

Мда... Ночь, устал, пространственное мышление отсутствует напрочь. Конечно же, при предложенном мной варианте "разлет" на краях будет еще больше первоначального. А надо бы "выгнуть" по окружности не малый отрезок d, а большой D -- тогда все нормально.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)