记录一个工作中遇到的小问题,奇数位是概率,偶数位是数值,给一个列表根据概率求数值。列表如:[50,3,30,5,20,10]
比如50%的概率返回3,30%的概率返回5,20%的概率返回10
-module(t).
-export([
test/0,
rand_weight/1
]).
test()->
WeightList = [50,3,30,5,20,10],
[
"RandWeight:",rand_weight(WeightList),
"Rand:1",rand_weight(1,WeightList),"Rand:50",rand_weight(50,WeightList),
"Rand:51",rand_weight(51,WeightList),"Rand:80",rand_weight(80,WeightList),
"Rand:81",rand_weight(81,WeightList),"Rand:100",rand_weight(100,WeightList)
].
%% ----------------------------------------------------
%% Func: rand_weight (T)
%% Description: 根据奇数位的概率随机求偶数位,如果概率为0则返回该Item
%% Args: 列表如:[50,a,30,b,20,c]
%% Returns:
%% ----------------------------------------------------
rand_weight(WeightList)->
case sum_odd(WeightList) of
0 ->
rand_weight(0,WeightList,[]);
OtherPerhaps ->
rand_weight(rand:uniform(OtherPerhaps),WeightList,[])
end.
%% 碰到0概率直接返回Item,不参与概率计算
rand_weight(_,[],NoPerhaps)->NoPerhaps;
rand_weight(Rand,[0,Value|List],NoPerhaps)->
rand_weight(Rand,List,[Value|NoPerhaps]);
%% 根据奇数位的概率随机求偶数位 列表如:[50,3,30,5,20,10]
rand_weight(Rand,[Perhaps,Value|T],NoPerhaps)->
if
Rand =< Perhaps -> [Value|NoPerhaps]; %% 返回[随机Value ++ 0概率Value]
true -> rand_weight(Rand-Perhaps,T,NoPerhaps)
end.
%% ----------------------------------------------------
%% Func: sum_odd (List)
%% Description: 计算奇数位的和
%% Args: [50,3,30,5,20,10]
%% Returns: 100
%% ----------------------------------------------------
sum_odd(List)->sum_odd(List,0).
sum_odd([],Sum)->Sum;
sum_odd([A,_B|List],Sum)->sum_odd(List,Sum+A).
思路:先把奇数和加起来,然后随机1个数Rand在范围 [1,奇数和] ,然后 Rand 依次减去奇数位的概率,减不动了就是最终的范围。