C способ сделать это:
float areaForPoly(const int numVerts, const Point *verts)
{
Point v2;
float area = 0.0f;
for (int i = 0; i<numVerts; i++){
v2 = verts[(i + 1) % numVerts];
area += verts[i].x*v2.y - verts[i].y*v2.x;
}
return area / 2.0f;
}
Вот взвешенная функция выбора с некоторым кодом, который ее использует.
import random
def WeightedPick(d):
r = random.uniform(0, sum(d.itervalues()))
s = 0.0
for k, w in d.iteritems():
s += w
if r < s: return k
return k
def Test():
k = {'A': 68, 'B': 62, 'C': 47, 'D': 16, 'E': 81}
results = {}
for x in xrange(10000):
p = WeightedPick(k)
results[p] = results.get(p, 0) + 1
print results
Test()
Я разработал алгоритм несколько лет назад, с приложением в Perl и SQL, вы можете прочитать об этом здесь , в комплекте с анализом и проверками, почему он (скорее всего) правильный.
Концепция проста: для каждого элемента выбирайте случайное число, тяните его через какую-то функцию, которая зависит от веса элементов и выбирает элемент с наименьшим значением.
функция:
x[i] = -log(1 - rand())/weight[i]
Алгоритм был бы таким.
Выберите число случайным образом между 1 и 274. Для этого вызовите функцию rand () (предположим, что она возвращает значение от 0 до 1), умножьте rand () на 274. Результирующее значение теперь должно находиться в диапазоне. Если его между 1 и 68, выберите A, если между 69 и 130 выберите B и так далее. Таким образом, ваша вероятность останется в живых, и ваша операция будет успешной.
PS: Я парень Java, не знаю синтаксиса Python.
Это должно сделать трюк:
>>> k = {'A': 68, 'B': 62, 'C': 47, 'D': 16, 'E': 81}
>>> import random
>>> def weighted_pick(dic):
... total = sum(dic.itervalues())
... pick = random.randint(0, total-1)
... tmp = 0
... for key, weight in dic.iteritems():
... tmp += weight
... if pick < tmp:
... return key
Самый простой способ сделать это, когда ваши веса являются относительно небольшими целыми числами (например, в вашем примере), состоит в том, чтобы построить длинную строку, содержащую все символы в соответствующих весах, и выбрать из нее случайный случай:
import random
d = {'A': 68, 'B': 62, 'C': 47, 'D': 16, 'E': 81}
s = ''.join(k*v for k,v in d.items())
random.choice(s)
Обратите внимание, что этот метод будет использовать довольно много памяти, если ваши весы большие, и в этом случае вы можете предпочесть другое решение.
следует также посмотреть на , что эта ссылка
делает два списка для k, например xk
и yk
from scipy import stats
custm = stats.rv_discrete(name='test', values=(xk, yk))
custm.rvs(size=1)