三国志11威力加强版吧 关注:150,252贴子:4,894,261

【技术水】关于Excel抽签器随机数据的讨论

取消只看楼主收藏回复

Excel是个好东西。


IP属地:天津1楼2021-10-05 21:17回复
    前段时间无聊的时候开了个脑洞,做了一个小小的抽签器。现在又在开吧剧了,正好放假有空写帖子,就把这个关于抽签器的脑洞写一下好了。水平有限,欢迎大家多多批评指正。


    IP属地:天津3楼2021-10-05 21:19
    回复
      一、均匀随机的局限性
      在一般的吧剧抽签器中,数据是怎么随机的呢?可能用的最多的就是excel自带的randbetween函数,这个函数很好用,比如说单元格内输入公式=randbetween(70,90),那么单元格内的结果就会随机到从70到90的21个整数,按F9就能刷新。但是,学过概率论的都知道,这种离散的随机方法属于“均匀随机”,它只能设定随机数据的上下限,但并不能改变随机数的分布。也就是说,抽到低数据、中数据和高数据的可能性是一样的。但是我们知道,在一个追求完美的制作者的角度,其实更希望随机数不是均匀的,而是在划定的范围内让随机到“极端值”的可能性更小些,让随机到“中庸值”的可能性更大些,这样才更能体现出模板设定的合理性。一个反例就是:对于武力数据,大将职业的随机范围在65到84之间,猛将职业的随机范围在75到94之间。那么大将与猛将随机到75-84这一区段的可能性都是50%,相乘就是25%,在这四分之一的概率内(对应到统计中就是约四分之一的签),大将与猛将的武力随机方案没有任何区别,因为都是75-84的均匀随机。这对于不同职业的选择是不太公平的,一定程度上消解了职业之间的差异性。


      IP属地:天津4楼2021-10-05 21:20
      回复
        另一个层面上,从设计者的角度考虑,如果选择了“大将”职业,按照正常的思路,一般都是在脑海中先浮现出“大将”所对应的大致数据范围,例如统率70-90,那么设计者当然更希望随机到80附近的可能性更大。超出这个范围的有没有可能?如果考虑到“有限的真实感”这一原则,好像大将随机到65或者更低一点也还说得过去,就相当于按照大将培养但是却不成才的少数情况。更高也可以,比如说92、93,就相当于奇才或天赋那种类型。然而,按照randbetween规则,如果把下限设定为60,上限设定为95,那么均值或者说期望就变成了77.5,偏离了设计这一职业的初衷。可见如果仅仅用这种简单的随机方案,是难以“鱼与熊掌兼得”的。
        那么,有没有一种办法让不同职业/模板的随机差异更明显一些,让每个模板的随机方案设定更有背景感、代入感一些,同时又不影响上下限设定?其实只要把“均匀随机”改成“不均匀随机”就行了。可喜的是,利用Excel公式就可以实现一些简单的不均匀随机规则,让中段数据更集中、随机概率更高,边缘数据的随机概率更小。更可喜的是,这种规则学起来相当简单。


        IP属地:天津6楼2021-10-05 21:21
        回复
          二、简单的不均匀随机方案(如果对公式不感兴趣可以跳过)
          Excel公式里最为常用的一个,不是sum,不是count,也不是vlookup,而是if。这个简单的条件分支判断为实现各种酷炫的操作提供了可能。就以随机数为例,如果想要不均匀随机,可以采用下面的方案:
          1.在单元格A1内输入公式=randbetween(1,10),产生分段随机数;
          2.在单元格B1内输入公式:
          =if(A1<=2,randbetween(60,74),
          if(A1<=8,randbetween(75,84),
          randbetween(85,94)))
          (这里提一个小tip,Excel输入公式是支持换行的,写长公式的时候更方便些)
          上面B1单元格内的这个公式在if内嵌套了一个if判断,相当于根据A1单元格的随机数产生了三种随机结果:
          当A1随机数为1-2时,B1内随机到60-74的15个数字;
          当A1随机数为3-8时,B1内随机到75-84的20个数字;
          当A1随机数为9-10时,B1内随机到85-94的15个数字。
          当然B1是最终随机结果,A1只是中间数据。换言之:随机数据分布到60-74的概率为20%,分布到75-84的概率为60%,分布到85-94的概率为20%。这样就实现了随机到中段范围数据的可能性更高,随机到边缘范围数据的可能性更低。随机到不同区段内的概率可以通过修改B1单元格内的分支条件的那几个数值来改变。如果想把概率更精细化,可以把A1里面的数值改大一些,比如说改成100;如果想要更多区段,无非就是在B1内多嵌套几个if而已。是不是很简单?
          当然,除了利用if外,别的方法也能做到不均匀随机——函数映射便是其中一种。仍然举例来说:
          1.在C1单元格内输入公式:=randbetween(61,90);
          2.在D1单元格内输入公式:=round(C1^2/100,0)。
          即把61-90的随机数平方后除以100再取整。D1单元格内的结果在37-81的范围内,然而它并不是从37-81的均匀分布。在37-81的前一半也就是37-59,实际上这一区段的随机概率是57%,也就是具有更高的可能性随机到数值较低的数据;而且数值越低,随机概率越高。如果把平方改成立方,这一规律会更明显。
          上面是平方函数的一个简单映射。当然Excel不只有平方和立方,还有开方、指数、对数等等,都可以照猫画虎弄出一个“不均匀随机”来。并且通过参数的设置,以及函数的叠加、嵌套,再加上一点点巧妙的算法,甚至可以搞出一套相当复杂的不均匀随机方案,只不过不太好把握就是了。


          IP属地:天津7楼2021-10-05 21:22
          回复
            三、概率密度函数(划重点,要考的)
            以上提出的不均匀随机方案,都是基于Excel公式直接得到的随机分布规则。相对于函数映射来说,显然if方法要更容易操作一些。其实做到这步已经可以了,毕竟抽签器也没多高要求。但对于强迫症来说,仍然会觉得这种方法不好看,它仍然有着可以精益求精的空间。
            这种方法有什么问题?
            首先,作为一个学渣和Excel公式小白,楼主看到那么多嵌套和数学公式一直觉得晕乎乎,对于掌握它果然还是比较抵触的——它对于新手不够友好。即使对于老手来说,设置公式、调节参数也是比较枯燥乏味的过程,并且这个过程不够直观可控,如果把做抽签器的热情都消耗在这里,就显得有点得不偿失了。
            其次,也是更重要的一点,用这种方法设置的公式,真的合理吗?分区段设置随机概率固然可以,不过这些区间、这些概率是不是也是脑子一热想出来的?函数映射的规则又有多少兼容性?如果存在一种“最佳”方案来设定随机规则,干嘛还要用这么复杂的嵌套复合呢?这种“最佳”随机方案,真的存在吗?
            答案是存在的。我们知道,对于一个人群的某个特征的分布,最常见也最合理的便是【正态分布】规则。如果把这种规则应用到武将数据随机中,那么数据随机的合理性一下子就有了,抽签器也一下子就高大上了起来。不过,在介绍正态分布之前呢,我们先来复习一下什么叫做【概率密度函数】。

            这个百度百科的定义很专业,但它复杂而冗长,我们做抽签器完全不需要知道这些,也不用管它是离散型还是连续型,也不要管如何归一化,我们这些小白只需要看下面这个图就可以了。(鼠绘轻喷)

            这条黑色曲线就是概率密度函数了。我们不用管它的函数值是什么,这个图里唯一有用的就是黄色部分,即区间与曲线围成的面积——这个黄色面积占这条曲线与横轴(数据范围)围成的总面积的比重就是概率。如果这个比重是0.3,就相当于往总面积里随机扔一粒芝麻,这粒芝麻分布到黄色面积里的概率就是30%,也就是说随机到50-75范围的概率是30%。至于随机到的具体值,就是芝麻位置所对应的横坐标,随机到小数的话取个整就行了。当然上面这个图并不是正态分布的概率密度函数图,正态分布是两端不封口的。


            IP属地:天津8楼2021-10-05 21:25
            回复
              在抽签器中,如果设计者可以自己【绘制】概率密度分布函数,显然就可以很容易很轻松地实现想要的随机规则了。顺便,我们来看一看前面写的那些用公式设置的随机规则,它们的概率密度函数长什么样子(示意图):

              显然,它们并不如正态分布好看,也不如正态分布合理。因为正态分布长这个样子:

              连续、对称、丝滑。那么问题来了,怎么样才能在Excel中做到这么好看的分布规律呢?能否把正态分布的概率密度函数引入到抽签器中呢?


              IP属地:天津9楼2021-10-05 21:27
              收起回复
                四、自定义数据分布的抽签器
                在引入正态分布之前,我们可以先试试看能不能在Excel中绘制自己想要的概率密度函数。当然,Excel是一个一个的单元格,不可能画出连续曲线来;不过,把这些单元格变小一点,似乎就可以用涂格子的办法来模拟出曲线效果。比如说下面这样。

                好像真的可以。在小方格里输入特殊符号,例如小数点".",再用条件格式把小方格涂绿,既能直观显示,又能用公式统计,一举两得。这样涂完以后,是不是就可以近似看作一条概率密度曲线了?(下面这个蓝线是截图的时候用鼠标画的)

                既然画曲线是可能的,那么接下来,就是想想办法怎么用画的这条概率密度曲线来抽取随机数据了。其实原理也很简单,仍然用前面提到的“扔芝麻”的办法,数一数一共有多少个绿色的格子,假如有50个,就用一个均匀随机函数randbetween(1,50),得到随机结果;假如随机到了39,然后只要从左到右数一下第39个绿色小方格所对应的横坐标就可以了。


                IP属地:天津10楼2021-10-05 21:31
                回复
                  当然了,尽管原理简单,设计起来还是要花一番工夫的。用各种各样的函数、添加辅助行辅助列、用公式设置条件格式什么的都是常规操作,这里就不再说明无聊的设计和调试过程,只展示一下画出的这条曲线怎么用。

                  上图是一个示例,在输入框中,可以输入单元格范围以及数据分布的上下限。单元格范围就是灰框部分,只有在这个范围的格子内打小数点,格子才会变绿;数据分布上下限则决定了刻度尺(图标上方那一行)上的数字。图中数据分布范围是70到90,很明显,现在画的这个曲线在83-84左右达到峰值,也就是说随机到这里的可能性是最大的。随机到70左右当然也有可能,不过因为左侧曲线很低,概率很小就是了。随机结果就用深绿色的竖线来显示,因为有小数,可能就会显示两条相邻的深绿色竖线了。
                  总的来说,相比于用公式设置随机规则的方案,直接涂格子画曲线的方法更加直观,对规则设计者也更友好。可是这个工作表的编码过程这么复杂,新手完全不会怎么办?简单的讲,不用考虑这些东西,因为这是一个轮子,或者说一个黑箱。使用的时候,只要勾勒曲线形状就可以了,并不需要去打开那些隐藏行、隐藏列,去查看里面复杂的公式;引用数据也可以直接把随机结果的那一个单元格引用过来,并且汇总到一起。如果复制出四个工作表,就可以画出5条不同的曲线,汇总以后就是一个武将的五维随机结果:


                  IP属地:天津11楼2021-10-05 21:33
                  收起回复
                    为了让五维的随机曲线设计更方便一些,还可以把五条曲线放在同一个工作表内,来定义不同类型武将五维的数据分布规律。

                    上面这个显然是“武将型”,五维中最容易拿到高数据的是武力,其次是统率,而后三维稍低些。但这并不意味着智力一定比武力低,仔细看上面画的曲线,智力是有可能比武力高的,只不过可能性比较小而已。甚至政治值都有可能比武力值高,只不过可能性微乎其微,毕竟作为武将培养的很少有成为文官的。除此之外,也可以定义出其他类型的人才,譬如五维都高的“英雄型”:

                    统武很低而魅力很高的“名媛型”:

                    政治最突出的“文官型”:

                    仅有武力突出的“猛将型”:

                    等等等等,各种类型的五维都可以自己定义,并且可以在汇总表中进行选择、抽签,得到当前选择类型的抽签结果——这便是【自定义数据分布】抽签器的雏形了。


                    IP属地:天津13楼2021-10-05 21:36
                    回复
                      五、正态分布与武将模板
                      现在,我们已经有了可以自定义的概率密度函数曲线,并且可以按照这条曲线所决定的分布规律来得到随机数。不过问题又来了,这样绘制的曲线,是“最佳方案”吗?虽然可以绘制出大致的中间高两头低的曲线形状,画曲线的时候多一格少一格好像也没什么所谓,但作为一个强迫症,仍然会觉得这样不够好,不够准确。另外,画曲线本身也是随心所欲,难以确定一个足够令人信服的标准。如果有一个标准化、自动化的东西,来代替人力,只要输入期望数据,就能让Excel自己把曲线画出来就好了。而这个“期望数据”,也就是我们所说的武将模板。
                      在模板抽签器中,一般会有一个模板武将库,里面收录了很多武将的五维信息。选择哪个模板,就意味着随机到的五维数据有更大可能性贴近这个模板。譬如,把血色周瑜的五维95/69/93/77/95收录进去,并且抽签的时候选择周瑜模板,那么随机到90/70/90/80/90的可能性显然要高于50/90/50/80/90。而这个规律利用正态分布的概率密度函数曲线,很容易实现。
                      当然,在画正态分布曲线之前,要先复习一下什么是正态分布。正态分布的概率密度函数长这样:

                      和前面一样,我们不用管这个复杂的公式,只需要看图。

                      在正态分布中,有两个重要的参数,一个是μ(读作miu),也叫均值;一个是σ(读作sigma),也叫标准差。上面这个图里,均值μ=80,意味着随机数据的均值是80,并且随机到80附近的可能性也最高。而标准差σ则决定了这条曲线的胖瘦,标准差越大,曲线越胖,也意味着随机结果更加分散;标准差越小,曲线越瘦,也意味着随机结果更加集中。对于正态分布,只要确定了这两个参数,曲线形状也就随之确定。如果把正态分布规则应用到模板抽签器,均值μ自然容易找,直接把模板数据作为μ即可;那么,标准差σ怎么确定呢


                      IP属地:天津14楼2021-10-05 21:39
                      回复
                        还记得中学的时候学过的“3σ原则”吗?对于正态分布而言,99.7%的数据会随机分布到[μ-3σ,μ+3σ]这个区间内,而区间外的几乎可以不考虑了。也就是说,如果我们希望均值是80,同时想要让武将的数据范围在80的上下15内浮动,那么就把15除以3,让标准差σ=5就可以了,这样几乎所有数据都会分布到65到95的区间。

                        把标准差暂定为5是比较合理的。如果模板数据是80,那么随机值取到65到95都有可能;但是边缘数据的随机概率仍旧小,从上面这个图可以看出,在65-70和90-95这两个区间,黄色面积只有很小一部分(2σ以外的只有5%)。而1σ以内即75-85的随机概率高达68%,越靠近均值80,随机到的可能性越高——这就是武将模板的意义,选择哪个武将作为模板,五维值就会贴近他,尽管仍然会有小概率偏离模板数据,但大多数情况还是会向模板靠拢。
                        那么接下来,仍然要研究一下如何用Excel做正态分布的随机抽签。既然已经有了概率密度函数图,那么只需要把填充小数点“.”的操作交给Excel公式就好了。还好,Excel自带函数里面有一个叫做NORMDIST的函数,它可以计算出正态分布概率密度曲线中某个点的函数值。利用这个,再加上一些归一化、整数化、比较大小等公式的设置,就能画出正态分布形状的绿色小方格来。而如果把标准差σ暂定为5,那么影响曲线形状的就只有武将模板的数据,也就是均值μ——也就是说,在模板库里选择好模板武将,数据的随机范围与分布规律就都确定好了。


                        IP属地:天津15楼2021-10-05 21:41
                        回复
                          同样地,不再展示公式的设计过程,我们只来看自动画图的结果。因为小数取整的关系,画的图可能并不是严格对称,不过也无伤大雅。

                          这里选择模板武将“青梅煮茶”,就自动生成了这个武将所对应的随机分布图,抽签的时候按F9刷新就可以了,也省去了让吧剧设计者自己涂格子的麻烦。当然,相对于通用型的“自定义数据分布”抽签器,正态分布规则的模板抽签器可以自主编辑的空间比较小,最多改一下σ,因此效率与自由度只能选择其一。


                          IP属地:天津17楼2021-10-05 21:42
                          回复
                            六、正态分布规则的改进
                            正态分布规则的抽签器有什么缺陷吗?
                            1.在前面的例子中,我们选取的“青梅煮茶”模板数据为70/44/42/34/88,自然没多大问题。但是如果是“风啸三国”呢?五维值91/73/94/63/73,如果把这个作为模板,标准差取5,而数据上限为100不变的话,那么图里面画出来的曲线是不全的,高数据区将被截断得很明显。

                            当然,即使曲线被截断了,就这么随机也不是不可以,但只有极端数据的曲线被截断而中间大部分都不受影响,略显不公。从数学的角度看,这样处理也不够丝滑连续。这是第一个问题。
                            2.回到武将模板的设计初衷本身,如果模板数据很高,那么在照着这个模板随机的时候,设计者是希望如何随机呢?如果单纯按照正态分布规律,那么随机到这个高数据左右两侧的概率是一样的,因为正态分布曲线是左右对称的。但是,模板数据是90的话已经很高了,设计者肯定不会希望有一半的可能性随机到比这个更高的数据,而是大概率落在低于90的区间。按正态分布规律来随机容易出现超模数据,这是第二个问题。


                            IP属地:天津18楼2021-10-05 21:44
                            回复
                              如何解决这两个问题?最直接的办法是把正态分布的曲线右半边直接去掉,这样随机到的数据绝对不会超过模板数据,相当于锁死上限。但是这个想法仅仅考虑了高数据区,而低数据区如果也应用这条规则,就会出现模板数据为10的时候,随机结果只可能是个位数的情况。那么有没有一种方案,让模板数据高的时候,大概率随机到低于模板的数值,模板数据低的时候,大概率随机到高于模板的数值,同时又满足丝滑要求,在模板数据中等的时候,随机到左右两侧的可能性一样呢?这句话可能有点绕,我们还是画个示意图来看一下。其实把这个需求用图形来表示,就是这样子的:

                              模板数据低,则更容易拿到高于模板的数据;模板数据高,则更容易拿到低于模板的数据;而且这个趋势随着模板数据的极端化而愈加明显。那么,如何设计算法来达到这个目的呢?
                              算法当然是有的。如果把这个不对称的曲线分成左右两半来看,每半边都可以看作是正态曲线的一半,只不过胖瘦不一样罢了。

                              因为曲线左右不对称,这条分界线的横坐标就不能叫均值了,我们先把它称作“中值”,便于区分。中值其实就是模板数据,对于中值比较高的曲线而言,中值左半边的σ更大些,曲线更胖些,随机概率更大些;中值右半边的σ更小些,曲线更瘦些,随机概率更小些;中值越高,不对称的程度越高。而中值低的曲线则正好相反。当中值为可抽签范围正中间时,比如说0~100的正中间即50,那么左右是对称的。(这条曲线专业一点的说法叫做左偏分布,它的偏度与中值有关。当右侧σ更大时,属于右偏分布)


                              IP属地:天津19楼2021-10-05 21:46
                              回复