怎么写一个带概率的随机抽取模型? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
zhimingcc
V2EX    程序员

怎么写一个带概率的随机抽取模型?

  •  
  •   zhimingcc 2014-11-03 10:34:37 +08:00 6014 次点击
    这是一个创建于 4074 天前的主题,其中的信息可能已经有所发展或是发生改变。
    对于[1,2,3,4,5,6,7]这个数组,如果随机抽取,肯定每个数的被抽取的概率都是1/7,
    代码大概是 Random.nextInt(7)就搞定了

    如果人为增加一个概率,比如1,2概率是0.25,3,4,5,6,7都是0.1的概率,
    该怎么写这样一个带概率的抽取模型?
    28 条回复    2015-03-05 01:31:03 +08:00
    mengzhuo
        1
    mengzhuo  
       2014-11-03 10:49:51 +08:00
    t/142820#reply11

    搭车同求更快的算法
    robbielj
        2
    robbielj  
       2014-11-03 10:53:23 +08:00 via iPhone
    最简单的说可以抽两次吧
    先分成[1,2]和剩下的,
    第一次random两个组,都是0.5
    第二次在组内random
    zhimingcc
        3
    zhimingcc  
    OP
       2014-11-03 10:54:57 +08:00
    @robbielj 不能这么写死啊,我只是举个例子。。。。比如用不同的概率分布模型
    andyzhshg
        4
    andyzhshg  
       2014-11-03 10:56:16 +08:00
    构造一个数组,里边1,2各25个,3,4,5,6,7各10个(不一定必须是25,10,可取最小整数倍,比如5和2),然后就继续用你说的算法就行了...不过我这办法看起来很矬的样子...
    CtrlSpace
        5
    CtrlSpace  
       2014-11-03 10:58:04 +08:00 via Android
    一个笨方法。
    弄一个长数组,按比例存放要抽取的数据,然后随机抽取数组下标。
    staticor
        6
    staticor  
       2014-11-03 10:58:42 +08:00
    加一个权重的字典
    zhimingcc
        7
    zhimingcc  
    OP
       2014-11-03 10:59:42 +08:00
    @mengzhuo GitHub被墙了。。。。先跪求翻墙软件,shadowsocksX感觉有点慢!
    guotie
        8
    guotie  
       2014-11-03 11:02:58 +08:00
    4楼的方法是最快的。
    lichao
        9
    lichao  
       2014-11-03 11:03:16 +08:00   1
    思路:

    i = nextInt(1..100)

    case i
    when 1..25 then 1
    when 26..50 then 2
    when 51..60 then 3
    when 61..70 then 4
    when 71..80 then 5
    when 81..90 then 6
    when 91..100 then 7
    whywhy36
        10
    whywhy36  
       2014-11-03 11:05:08 +08:00
    sorry, no Chinese Input Method :-(

    1. init one mapping according to the probability
    1-25 -> 0
    26-50 -> 1
    51-60 -> 2
    ...
    2. Random.nextInt(100)
    3. pick the index from the mapping
    4. get the number ...
    zhimingcc
        11
    zhimingcc  
    OP
       2014-11-03 11:08:03 +08:00
    @lichao 赞一个!!简单但容易实现!!
    yxz00
        12
    yxz00  
       2014-11-03 11:20:19 +08:00
    如果精度要求不是很高,四楼的方法不错
    khowarizmi
        13
    khowarizmi  
       2014-11-03 11:50:53 +08:00
    发现跟楼上的思路重复了,但还是写一下吧.(仅仅针对lz给的例子)

    p = Math.random()
    if 0 < p < 0.25
    x = 1
    if 0.25 < p < 0.5
    x = 2
    ....
    delphiqin
        14
    delphiqin  
       2014-11-03 12:30:51 +08:00
    delphiqin
        15
    delphiqin  
       2014-11-03 12:33:08 +08:00
    额,发代码失败,重来……
    https://gist.github.com/DelphiQin/37379f79fa03c3ff84d5
    xiaoxiaoming
        17
    xiaoxiaoming  
       2014-11-03 13:45:16 +08:00
    可以用一个 类似 轮盘转法,命中率就是长度 或者是面积
    jokester
        18
    jokester  
       2014-11-03 14:34:58 +08:00
    Weighted random sampling with a reservoir 这篇论文给出了一个保证one-pass的算法
    feiyuanqiu
        19
    feiyuanqiu  
       2014-11-03 14:36:54 +08:00
    php:

    function rand_weight($numbers)
    {
    $total = 0;
    $dist = array();
    foreach ($numbers as $num => $weight) {
    $total += $weight;
    $dist[$num] = $total;
    }
    $rand = mt_rand(0, $total - 1);
    foreach ($dist as $num => $weights) {
    if ($rand < $weights) { return $num; }
    }
    }
    feiyuanqiu
        20
    feiyuanqiu  
       2014-11-03 14:44:50 +08:00
    使用:
    $a = array(
    'this' => 10, // 50%
    'is' => 2, // 10%
    'a' => 5, // 25%
    'test' => 3, // 15%
    );
    $result = array();
    for ($i=0; $i < 100; $i++) {
    $result[] = rand_weight($a);
    }
    print_r(array_count_values($result));exit;

    // 结果: Array ( [a] => 24 [this] => 50 [is] => 8 [test] => 18 )
    jokester
        21
    jokester  
       2014-11-03 14:47:09 +08:00
    @jokester 补充. 那个论文是n中抽m(m<=n)的方法. n中抽1不用那么复杂.
    zoowii
        22
    zoowii  
       2014-11-03 14:47:31 +08:00
    生成一个[0, 1)的小数,然后按权重分配这段长为1的线段.然后看这个随机生成的小数在哪个区间即可
    bingwenshi
        23
    bingwenshi  
       2014-11-03 14:51:20 +08:00
    刚好前几天研究过类似的问题, 楼主可以看下我的这篇博客

    http://segmentfault.com/blog/shibingwen/1190000000735405
    bingwenshi
        24
    bingwenshi  
       2014-11-03 14:56:11 +08:00
    方法不一定比楼上各位的好, 但是思路会比较清晰点
    lygmqkl
        25
    lygmqkl  
       2014-11-03 16:08:43 +08:00
    @lichao 这个方法好,不局限在目标array,跳出来构建一个概率数组,然后根据概率数组获得的值直接取整对应到目标array
    walleL
        26
    walleL  
       2014-11-03 20:20:26 +08:00
    圆桌算法 代码参考 @feiyuanqiu
    游戏里面经常用到
    xiaowangge
        27
    xiaowangge  
       2014-11-03 22:18:34 +08:00 via Android
    游戏开发用到的是,填写成配置文件。
    yangzh
        28
    yangzh  
       2015-03-05 01:31:03 +08:00 via iPhone
    已知了概率分布的概率累积函数 F(x),也可以从均匀分布 U[0,1] 中随机取 u ,再求 x=F^(-1)(u) ,x 即是想要随机样本。

    此为统计学上的标准答案。建议楼主找个周围学过概率学的朋友问问。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3264 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 10:54 PVG 18:54 LAX 02:54 JFK 05:54
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86