如何高效的生成 多次随机的结果? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
edward1987

如何高效的生成 多次随机的结果?

  •  1
     
  •   edward1987 2022 年 8 月 25 日 2709 次点击
    这是一个创建于 1338 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求举例: 有个抽奖活动, 抽奖概率是 a:10%,b:30%,c:40%,d:20% 如果要支持批量抽,然后返回聚合结果,比如 用户可以一键批量抽 1000 次,然后返回 {a:104,b:288 ....的聚合结果

    如果 1000 次要 每次都去取随机,然后统计聚合感觉太低效了, 有没有大佬有高效点的方案?

    第 1 条附言    2022 年 8 月 25 日
    哈哈哈哈主要还是求知欲想了解下方案,目前比较理想的方案应该是楼里的同学说的: 取期望值+浮动

    最后还是选择了直接随机 1000 次,因为大部分情况下 随机次数都比较少
    21 条回复    2022-08-26 11:07:40 +08:00
    imdong
        1
    imdong  
       2022 年 8 月 25 日 via iPhone
    数量不多,直接循环随机,数量太多,先算出他中奖的可能性与数量,然后扣掉奖品,剩下的全部填充为未中奖。
    edward1987
        2
    edward1987  
    OP
       2022 年 8 月 25 日
    `先算出他中奖的可能性与数量`
    @imdong 关键就是这一步呀,怎么高效的算出来呢?
    TimePPT
        3
    TimePPT  
    PRO
       2022 年 8 月 25 日
    你抽 1000 次这种量级,abcd 出现的个数约等于总次数乘以概率啊。直接算出来后上下浮动个随机数,加和等于 1000 就行。
    lmshl
        4
    lmshl  
       2022 年 8 月 25 日
    才 1000 次,说白了就是 1000 次 mul + add + mod ,暴力算也不过几微秒的事,这还要什么优化?
    就算是一百万次也不值得优化
    edward1987
        5
    edward1987  
    OP
       2022 年 8 月 25 日
    @TimePPT 是个好想法, 不过这个浮动的随机数不知道怎么取比较合适
    Vegetable
        6
    Vegetable  
       2022 年 8 月 25 日
    这里居然真的有人用“随机 10 次”来实现 10 连抽,过于良心引起不适。

    如果你想得到真实的结果,那其实可以算,10% * 10 能得到 1..10 这 10 种情况,每种情况出现的概率都是能算出来的。所以你只需要根据这个权重随机一次就能得到这 10 连抽应该得到几个 a 。
    Vegetable
        7
    Vegetable  
       2022 年 8 月 25 日
    @Vegetable 哦不对,是 0..10
    UIXX
        8
    UIXX  
       2022 年 8 月 25 日   3
    看来 OP 是个良心策划,铁了心践行大数定律,其实这个很简单。直接排出 100 ,300 ,400 ,200 ,然后加扰动值,这个扰动值跟批量的次数有关,批量的次数越大扰动值越小,至于是线性还是非线性,是一次方还是二次方,就跟 OP 的良心大小有关了。
    InDom
        9
    InDom  
       2022 年 8 月 25 日
    把中奖概率 * 抽奖次数 = 中奖个数,然后随机给个偏差,不管需要抽多少次,你有几个奖品,就需要随机几次。

    你这设置概率 100% 中奖,那就是抽一千次

    c 有 40% ± rand% * 1000 次 = 104 个 1000 - 104
    b 有 30% ± rand% * 1000 次 = 288 个 1000 - 104 - 288

    以此类推,建议把中奖率排个序,先从这中奖率高的随机,随机完就把总次数减掉已派奖的,抽完就不抽了。

    别跟我讲公平,公平你就该一次次抽奖。
    sillydaddy
        10
    sillydaddy  
       2022 年 8 月 25 日   1
    楼主如果想要严谨的话,应该是利用「二项式分布」: https://zh.m.wikipedia.org/zh/%E4%BA%8C%E9%A0%85%E5%BC%8F%E5%88%86%E5%B8%83

    ```
    二项分布 B(n,p),指的是单次实验成功概率是 p ,那么经过 n 次实验,成功次数的概率分布。

    成功 k 次的概率是
    {\displaystyle f(k,n,p)=\Pr(X=k)={n \choose k}p^{k}(1-p)^{n-k}}
    ```

    先把 a 的中奖次数算出来:a 成功的概率 p=10%=0.1 ,实验 1000 次,成功次数小于 k 的分布,是二项分布 B(n,p)的累计分布函数,所以取一个随机值,与累积分布函数对应,得出 a 的中奖次数;
    然后把 b 的中奖次数用类似的方法算出来,然后是 c ,最后 d 就不用计算了。
    icyalala
        11
    icyalala  
       2022 年 8 月 25 日
    @sillydaddy 应该是多项分布吧
    mxT52CRuqR6o5
        12
    mxT52CRuqR6o5  
       2022 年 8 月 25 日 via Android
    取 1000 次随机数能消耗多少性能,别浪费时间优化这个没多大收益的事情了
    sillydaddy
        13
    sillydaddy  
       2022 年 8 月 25 日
    @icyalala
    是多项分布。但是我想不到多项分布怎么去计算(多项分布的累积分布函数不知道怎么弄),所以把它拆成多个二项分布,二项分布可以利用它的累积分布函数,直接得出中奖次数。

    不过忘了说了,二项分布本身的计算很直接,但这个累积分布函数不知道有没有高效的计算方法,没有的话还不如直接循环 1000 次 random 呢。
    leimao
        span class="no">14
    leimao  
       2022 年 8 月 25 日 via iPhone
    Multinomial Distribution
    Jooooooooo
        15
    Jooooooooo  
       2022 年 8 月 25 日
    如果你真的用普通随机会被骂的, 肯定不行.
    leimao
        17
    leimao  
       2022 年 8 月 25 日 via iPhone
    我有一节简单讲了讲 Multinomial Distribution 怎么推导的
    https://leimao.github.io/blog/Introduction-to-Dirichlet-Distribution/
    2kCS5c0b0ITXE5k2
        18
    2kCS5c0b0ITXE5k2  
       2022 年 8 月 25 日
    可以看下 Alias Method.
    2kCS5c0b0ITXE5k2
        19
    2kCS5c0b0ITXE5k2  
       2022 年 8 月 25 日
    #18 构造表的时间复杂度:O(n) 后续实际抽选的时间复杂度:O(1)
    edward1987
        20
    edward1987  
    OP
       2022 年 8 月 26 日
    @emeab 应该不行,因为我这个次数是不确定的,不是固定的 1000 次

    @leimao 多谢,看着有亿点复杂,我研究下~
    libook
        21
    libook  
       2022 年 8 月 26 日
    中奖名额少的话,可以提前算出来第多少次中奖,然后记录下来,抽的时候要没抽到这些次数就不中奖。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4811 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 79ms UTC 09:41 PVG 17:41 LAX 02:41 JFK 05:41
    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