Рандом с вероятносью, хелп пж
Допустим есть функцию randomChanses(map)
Т.е. на входе у нас словарь, в котором ключ-символ, а значение-вероятность появление этого символа. Т.е. допустим есть такой набор: {'a'=10,'b'=20,'c'=30}. Т.е. появление a 1к10, b 1к20, с 1к30. Помогите накидать функцию, которое бы возвращала рандомное значение, учитываю вероятность. Была идея просто создать список, в который поместить 'a' 10 раз, 'b' 20 раз и т.д. Но это не совсем то, да и если шансы будут 1к1000, то слишком долго будет создаваться список. |
Цитата:
Цитата:
в общем, поподробнее бы условие. |
LimonDK,
const fun = n => n < 0.16 ? 'a' : n < .5 ? 'b' : 'c'; alert(fun(Math.random())); |
рони,
Цитата:
30 раз запустили. В среднем должно быть 1 раз с, 1.5 раза b, 3 раза а. Разве не так? |
voraa,
Цитата:
<script> const fun = n => n < 0.16 ? 'a' : n < .5 ? 'b' : 'c'; const obj = {}; for (let i = 0; i < 60; i++) { let key = fun(Math.random()); obj[key] = 1 + (obj[key] >> 0); } document.write(JSON.stringify(obj, "", 4)) </script> |
Цитата:
потом из этого списка равновероятно выбираем элемент, и он оказывается одним из символов. это как-раз то, что рони сделал. В общем виде примерно так: function rnd(map) { const keys = Object.keys(map); if (!keys.length) { return undefined; } const sum = keys.reduce((s, key) => s + map[key], 0); const r = Math.random() * sum; let acc = 0; for (let i = 0; i < keys.length; ++i) { acc += map[keys[i]]; if (acc > r) { return keys[i]; } } return keys[keys.length - 1]; } // для проверки рандомности function getStat(map, iters) { const stat = Object.create(null); Object.keys(map).forEach(key => { stat[key] = 0; }); for (let i = 0; i < iters; ++i) { const v = rnd(map); stat[v]++; } Object.keys(map).forEach(key => { stat[key] = stat[key] / iters; }); return stat; } alert(JSON.stringify(getStat({'a': 10,'b': 20,'c': 30}, 40000), '', 4)); |
Цитата:
|
то есть вероятности - это на самом деле обратные значения от тех, что в словаре?
гарантируется, что сумма этих обратных значений всегда не больше 1 ? |
Цитата:
находим сумму всех весов 10 + 20 + 30 = 60//порядок не имеет значения первый if 10 * 1/60 второй if (10 + 20) * 1/60 else всё остальное итого if(n < 0.16) return 'a'; else if(n < .5) return 'b'; else return 'c' для примера другой порядок с : 30 , a : 10, b : 20 30 * 1/60 (30 + 10) * 1/60 if(n < .5) return 'c'; else if(n < .66) return 'a'; else return 'b' |
Тогда с таким же успехом можно было написать
{a:1, b: 2: c:3} Никакой разницы. Но между 1/2 и 1/20 для b все таки есть разница. |
Часовой пояс GMT +3, время: 11:10. |