Вероятности при последовательном отсечении шансов
Добавлено: Пт ноя 28, 2014 12:31 pm
В нашем коде можно встретить следующие конструкции, последовательные проверки на 25% (или любой другой) шанс выпадения.
Разработчик видимо предполагал, что все варианты равновероятные.
Но для неподготовленного человека тут скрыт подвох, каждый следующий шаг в лесенке elseif
уменьшает шанс выпадения за счет выбивания большого количества шансов на первых шагах.
Визуально - это как пирамида - чем выше от земли тем меньше шанс.
Посмотрим на примере:
фактически, этот код можно улучшить так, обратившись 1 раз за получением случайного
числа (и округляя дробные вероятности до целого):
или даже так, если нужно получить однотипное значение:
Если же нужно выполнить разные последовательности кода в каждом блоке - вот тут не хватает оператора swith,
которые разработчики Lua отказываются сделать.
Хотя можно выкрутиться и так:
Если разработчик не подозревает о такой лесенке шансов и ставит последним условием 1%, то можете представить,
какой шанс того, что этот 1% от (x/100 )^n шагов может выпасть. =)
Разработчик видимо предполагал, что все варианты равновероятные.
Но для неподготовленного человека тут скрыт подвох, каждый следующий шаг в лесенке elseif
уменьшает шанс выпадения за счет выбивания большого количества шансов на первых шагах.
Визуально - это как пирамида - чем выше от земли тем меньше шанс.
Посмотрим на примере:
Код: Выделить всё
if math.random(1, 100) > 75 then -- 25% от 100% = 25% шанс от исходных 100%
...
elseif math.random(1, 100) > 75 then -- 25% от 75/100 = 18,75% шанс от исходных 100%
...
elseif math.random(1, 100) > 75 then -- 25% от 75/100 * 75/100 = 14,0625% шанс от исходных 100%
...
elseif math.random(1, 100) > 75 then -- 25% от 75/100 * 75/100 * 75/100 = 10,546875% шанс от исходных 100%
...
else -- остаток 75% от 75/100 * 75/100 * 75/100 = 31,640625% шанс от исходных 100%
...
end
числа (и округляя дробные вероятности до целого):
Код: Выделить всё
local rnd = math.random(1, 100)
if rnd > 75 then -- 25% от 100% = 25% шанс от исходных 100%
...
elseif rnd > 56 then -- 25% от 75/100 = 18,75% шанс от исходных 100%
...
elseif rnd > 42 then -- 25% от 75/100 * 75/100 = 14,0625% шанс от исходных 100%
...
elseif rnd > 32 then -- 25% от 75/100 * 75/100 * 75/100 = 10,546875% шанс от исходных 100%
...
else -- остаток 75% от 75/100 * 75/100 * 75/100 = 31,640625% шанс от исходных 100%
...
end
Код: Выделить всё
local rnd_table = {1, 2, 3, 4, 5}
local value = rnd_table[math.random(1, 5)]
...
которые разработчики Lua отказываются сделать.
Хотя можно выкрутиться и так:
Код: Выделить всё
local rnd_table = {
[1] = function () {...},
[2] = function () {...},
[3] = function () {...},
[4] = function () {...},
[5] = function () {...} }
rnd_table[math.random(1, 5)] () -- получаем функцию из таблицы и выполняем
какой шанс того, что этот 1% от (x/100 )^n шагов может выпасть. =)