请教抽奖算法 奖品是 1-100 元整数 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
Windowsxpplayer

请教抽奖算法 奖品是 1-100 元整数

  •  
  •   Windowsxpplayer 2020 年 2 月 12 日 via Android 4838 次点击
    这是一个创建于 2264 天前的主题,其中的信息可能已经有所发展或是发生改变。

    抽奖算法

    奖品是 1-100 元整数

    要求金额越大抽中概率越小, 可以设置数学期望。

    各位有什么思路?

    25 条回复    2020-02-14 22:56:13 +08:00
    oIMOo
        1
    oIMOo  
       2020 年 2 月 12 日   1
    笨办法:
    把 1 - 100 按照你的意愿放入一个 list 里面
    假设抽中 1 元的概率是抽中 100 元的 666 倍,那就在 list 里面放 1 个 100 和 666 个 1,其它金额同理。
    然后随机选列表里面的一个数字。

    没睡好,脑子不太转,等楼下……
    shadeofgod
        2
    shadeofgod  
       2020 年 2 月 12 日
    ```js
    function rand(max) {
    const _rand = () => ~~(Math.random() * max);
    const a = _rand();
    return (Math.random() > a / 100) ? a : _rand();
    }
    ```
    shadeofgod
        3
    shadeofgod  
       2020 年 2 月 12 日
    哦 上面这个只是 max = 100 的时候的,随便写了一下
    hearfish
      &nbs; 4
    hearfish  
       2020 年 2 月 12 日
    weighted random, 金额越大权重越小

    有兴趣的话可以去看看 Alias Method
    ferock
        5
    ferock  
    PRO
       2020 年 2 月 12 日   1
    @oIMOo #1

    这个方案并不是不可行
    st2udio
        6
    st2udio  
       2020 年 2 月 12 日
    要有个背景吧。抽奖人数是否可估,奖品总数是否固定。避免没被抽完或提前抽完。
    daozhihun
        7
    daozhihun  
       2020 年 2 月 12 日   1
    有个简单的办法。
    假如 1 的概率是 10 的 10 倍,是 100 的 100 倍
    则可以考虑 1 ~ 100 为 1,101 ~ 199 为 2,……,5048 ~ 5049 为 99,5050 为 100。
    则生成 1 ~ 5050 区间的随机数,按照上面的算法判断对应的区间表示哪个数,比如生成 145 对应的数字是 2。
    这样的话 1 ~ 100 的概率递减,且 1 是 10 的 10 倍,是 100 的 100 倍
    daozhihun
        8
    daozhihun  
       2020 年 2 月 12 日   1
    @daozhihun 概率算错了,但是思路大致这样。总的来说按照概率大小分成不同区间,再计算生成的随机数所在的区间对应的数字
    xupefei
        9
    xupefei  
       2020 年 2 月 12 日
    带权重的水塘抽样?
    ylsc633
        10
    ylsc633  
       2020 年 2 月 12 日
    http://interview.wzcu.com/%E8%AE%BE%E8%AE%A1%E9%A2%98/%E5%B8%A6%E6%9C%89%E6%9D%83%E9%87%8D%E7%9A%84%E9%9A%8F%E6%9C%BA%E7%AE%97%E6%B3%95.html

    实现很简单 不过看需求

    这个概率 跟 奖品数量有没有关系!

    比如 2 个奖品! 100 个人抽!每人一次机会!

    跟库存有关的话 第一个人没中,第二个人概率就是 2/99
    跟库存无关的话 第一个人没中,第二个人概率还是 2/100
    ipwx
        11
    ipwx  
       2020 年 2 月 12 日
    metamask
        12
    metamask  
       2020 年 2 月 12 日
    看需求,
    比如总金额固定,最简单的就是你事先生成 数组,你自己按比例配进去;

    还有一种比较简单的,就是你划定好区间,随机生成一个数,然后用二分插入的算法做。
    x = [1, 100, 300, 400 ... 9990, 10000]
    y = [1, 2, 3 ... 100]

    index = bisect_search(x)
    y[index]
    ccoming
        13
    ccoming  
       2020 年 2 月 12 日
    会出现全部不中奖的情况么?
    ETiV
        14
    ETiV  
       2020 年 2 月 12 日
    https://zh.wikipedia.org/wiki/%E6%B3%8A%E6%9D%BE%E5%88%86%E4%BD%88

    我首先想到的是泊松分布 lambda=1 的曲线

    ----
    话说这种出真钱的概率不能是前后无关的吧
    比如服务器记录一下今天 100 块已经被抽出去了,那今天就不应该再出现 100 块了…
    dji38838c
        15
    dji38838c  
       2020 年 2 月 12 日
    要求金额越大抽中概率越小,并且可以设定期望值,可以用几何分布。
    可以设定期待值 expected_value, 和抽奖的次数 n
    np.random.geometric(p = 1.0/expected_value, size = n)
    注意,如果期待值高的话,随机产生的值可能超出 100。
    oIMOo
        16
    oIMOo  
       2020 年 2 月 12 日
    楼主不要被我 1 楼的回复迷惑,我现在清醒了。
    #4 的关键词可以参考,下面这个也可以看看
    https://medium.com/@peterkellyonline/weighted-random-selection-3ff222917eb6
    kdashl
        17
    kdashl  
       2020 年 2 月 12 日
    1 加到 100 是 5050...100 就是 1/5050,99 就是 2/5050.....以此类推到 1 就是 100/5050
    CEBBCAT
        18
    CEBBCAT  
       2020 年 2 月 13 日 via Android
    这个我写过,网上也是稍微搜下就有。要是明天我还记得就过来贴代码
    CEBBCAT
        19
    CEBBCAT  
       2020 年 2 月 13 日 via Android
    一个变量存权重之和,random 一个 r 然后对刚才那个 sum 求模。循环加权值,直到加和大于等于得到的模
    VDimos
        20
    VDimos  
       2020 年 2 月 13 日 via Android
    box muller 算法,不知道行不行
    smdbh
        21
    smdbh  
       2020 年 2 月 13 日
    最简单的方法,设一个数组, 数字越小,重复个数就越多,然后 随机函数抽一个。
    coderEOS
        22
    coderEOS  
       2020 年 2 月 13 日
    @rets = [1, 2, 3, 4, 15]
    @quan = [10, 30, 50, 70, 100]
    @randMax = @quan.inject(:+)
    def clacOneRet
    randV = rand(@randMax) + 1
    @quan.each_index do |i|
    randV = randV - @quan[i]
    return @rets[i] if randV <= 0
    end
    return -1
    end

    nums = {}
    @rets.each {|k| nums[k] = 0}
    for i in 1..1000
    v = clacOneRet
    nums[v] = nums[v].to_i + 1
    end
    puts nums ## {1=>31, 2=>123, 3=>182, 4=>263, 15=>401}
    coderEOS
        23
    coderEOS  
       2020 年 2 月 13 日
    <body class="vscode-light">
    <h1 id="%e5%85%b6%e5%ae%9e%e5%b0%b1%e6%98%af%e7%ae%80%e5%8d%95%e7%9a%84%e5%b8%a6%e6%9d%83%e7%ae%97%e6%b3%95">其实就是简单的带权算法</h1>
    <pre><code class="language-ruby"><div>@rets = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">15</span>]
    @quan = [<span class="hljs-number">10</span>, <span class="hljs-number">30</span>, <span class="hljs-number">50</span>, <span class="hljs-number">70</span>, <span class="hljs-number">100</span>]
    @randMax = @quan.inject(<span class="hljs-symbol">:+</span>)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">clacOneRet</span></span>
    randV = rand(@randMax) + <span class="hljs-number">1</span>
    @quan.each_index <span class="hljs-keyword">do</span> <span class="hljs-params">|i|</span>
    randV = randV - @quan[i]
    <span class="hljs-keyword">return</span> @rets[i] <span class="hljs-keyword">if</span> randV &lt;= <span class="hljs-number">0</span>
    <span class="hljs-keyword">end</span>
    <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>
    <span class="hljs-keyword">end</span>

    nums = {}
    @rets.each {<span class="hljs-params">|k|</span> nums[k] = <span class="hljs-number">0</span>}
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-number">1</span>..<span class="hljs-number">1000</span>
    v = clacOneRet
    nums[v] = nums[v].to_i + <span class="hljs-number">1</span>
    <span class="hljs-keyword">end</span>
    puts nums <span class="hljs-comment">## {1=&gt;31, 2=&gt;123, 3=&gt;182, 4=&gt;263, 15=&gt;401}</span>
    </div></code></pre>
    pmispig
        24
    pmispig  
       2020 年 2 月 13 日
    最简单的实现方法 100 元 = 1% 1 元=99%
    这个几率太高的化,统一乘以一个比例
    Windowsxpplayer
        25
    Windowsxpplayer  
    OP
       2020 年 2 月 14 日 via Android
    @st2udio 都是不限, 奖品不是现金而且余额
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2891 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 70ms UTC 03:24 PVG 11:24 LAX 20:24 JFK 23:24
    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