распределять набор элементов между N ведрами на основе весов

0

Для N ведер и некоторых элементов E1 (W1) E2 (W2). Я хочу распространять N ведер между элементами Ei на основе их весов Wi

For example N = 20, W1 = 5 W2 = 5 W3 = 10 so
E1_buckets = 20*(5/20) = 5
E2_buckets = 20*(5/20) = 5
E3_buckets = 20*(10/20) = 10

Я должен иметь отдельные ведра (5 + 5 + 10 = 20), суммировать до N. Я думал о том, чтобы делать что-то вроде этого

bucket[i] = round(N*(W[i]/TOT_WGT) where W[i] = element weight, and TOT_WGT = sum of weights W[i]

Кажется, однако, что я мог ошибиться от неточности в представлении чисел с плавающей запятой. Возможно ли с арифметикой с плавающей запятой гарантировать, что сумма ведер всегда будет равна N?

Альтернативным способом было бы всегда брать слово и назначать избыток некоторому случайному элементу

bucket[i] = floor(N*(W[i]/TOT_WGT)
bucket[k] += (N-sum_of_buckets)

Хотя это не гарантирует идеальный вес, я получаю ведра, суммирующие N. Любые мысли, я что-то упускаю, и есть возможно простой способ сделать это?

Теги:
algorithm

2 ответа

1
Лучший ответ

Вместо вычисления количества ведер в элементе я вы могли бы вычислить количество ковшей в первых элементах i, а затем вычесть количество ведер в первых элементах i-1, чтобы получить количество ведер в элементе i.

В этом случае количество ведер в первых элементах я может быть круглым (N * SUM_k_up_to_i (W [k])/TOT_WGT). В этом случае количество элементов во всех ковших будет круглым (N * TOT_WGT/TOT_WGT), которое, скорее всего, будет суммироваться с N, и которое вы могли бы в любом случае заменить на N, и вам гарантировано, что сумма ковшей будет N.

  • 0
    Элегантно и просто! Спасибо, сэр
1

Лучший способ сделать это - не представлять бин, используя его ширину. Вы пытаетесь представить непрерывный интервал, и сделать это, взяв объединение подынтервалов, выровненных ~ правым, сложнее сказать.

Вместо этого вычисляйте позиции внутренних разделителей ({5, 10} в вашем примере), а затем представляйте свои ведра в виде пар конечных точек (конечные точки: {0, 5, 10, 20} в примере). Всякий раз, когда вам нужна ширина бина, верните разницу между этим бином двух конечных точек. Да, ширина бункеров может быть немного от веса, но если ваше приложение чувствительно к этой ошибке, вы действительно должны использовать точный числовой тип.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню