Java 从5个骰子卷中,生成一个范围为[1-100]的随机数

Java 从5个骰子卷中,生成一个范围为[1-100]的随机数,java,random,range,dice,Java,Random,Range,Dice,我正在进行一些编码练习,遇到了一些问题: 从5个骰子(6面)掷骰中,生成[1-100]范围内的随机数 我实现了下面的方法,但是返回的数字不是随机的(调用函数1000000次,有几个数字在1-100中从未出现) publicstaticint生成器(){ Random rand=新的Random(); 整数骰子=0; 对于(int i=0;i0值,则生成一个以6为基数的5位数字。我们都知道6^5=7776独特的可能性 对于这个,我将给你们一个有偏的随机解 int total = 0; int[]

我正在进行一些编码练习,遇到了一些问题:

从5个骰子(6面)掷骰中,生成[1-100]范围内的随机数

我实现了下面的方法,但是返回的数字不是随机的(调用函数1000000次,有几个数字在1-100中从未出现)

publicstaticint生成器(){
Random rand=新的Random();
整数骰子=0;
对于(int i=0;i<5;i++){
骰子+=随机数下一个(6)+1;
}
int originalStart=5;
int originalEnd=30;
int newStart=1;
int newEnd=100;
双刻度=(双刻度)(newEnd-newStart)/(originalEnd-originalStart);
返回(整数)(newStart+((骰子-原始开始)*刻度));
}

问题是5-30中没有足够的随机值来映射一对一到1-100的间隔。这意味着某些价值观注定永远不会出现;这些“丢失”值的数量取决于两个间隔的大小比

然而,你可以更有效地利用骰子的力量。我是这样做的:

方法1

  • 使用第一个骰子的结果从中选择一个子区间 6个大小为16.5(99/6)的等分间隔
  • 使用第二个骰子的结果从步骤1中选择的子间隔的6个相等子间隔中选择一个子间隔
  • 使用。。。我想你知道接下来会发生什么
  • 方法2

    在6进制系统中使用数字构造随机数。也就是说,第一个骰子将是以6为基数的数字的第一个数字,第二个骰子将是第二个数字,等等。

    然后转换为基数10,除以(46656/99)。你应该有你的随机数。事实上,你只能使用3个骰子,当然,剩下的两个是多余的。

    好的,所以5个骰子卷,每个有6个选项。如果未订购,则如上所述,其范围为5-30,不足以满足1-100的要求

    您需要假设一个顺序,这将为您提供1,1,1,1-6,6,6,6(以6为基数)的刻度。假设1-->0值,则生成一个以6为基数的5位数字。我们都知道6^5=7776独特的可能性

    对于这个,我将给你们一个有偏的随机解

    int total = 0;
    int[] diceRolls;
    for (int roll : diceRolls) {
        total = total*6 + roll - 1;
    }
    
    return total % 100 + 1;
    
    感谢JosEdu澄清支架要求


    此外,如果您想取消此偏差,您可以将范围除以我上面描述中给出的maxval,然后再乘以总数(然后添加偏移量),但您仍需要确定所使用的舍入规则。

    滚动6面模具5次,结果是6^5=7776个可能的序列,所有序列的概率相同。理想情况下,您可能希望将这些序列划分为100组大小相等的序列,这样您就可以得到[1-100]rng,但由于7776不能被100平均整除,所以这是不可能的。为了最大限度地减少偏差,您所能做的就是分别映射到78个序列的76个组和77个序列的24个组。将(有序)骰子卷编码为基数为6的数字n,并返回1+(n%100)


    不仅没有办法用5个骰子卷来消除偏差,而且没有多少个骰子卷可以完全消除偏差。不存在6^k可被100整除的k值(考虑素因子分解)。这并不意味着没有办法消除偏差,它只是意味着你不能使用保证在任何特定数量的骰子滚动后终止的程序来消除偏差。但是你可以做3个掷骰子,产生6^3=216个编码为基数6的序列n,如果n<200,返回1+(n%100)。问题是,如果n>=200,则必须重复该过程,并不断重复,直到n<200。这样就不会有偏见,但也不会限制你在循环中停留的时间。但是,由于每次重复的概率只有16/216,从实际的角度来看,这并不是什么大问题。

    不要每次创建一个新的
    Random
    实例,为每个方法调用维护一个实例。虽然你可能仍然会得到“丢失”的数字,但范围将更加随机。只需使用第一个掷骰子。它将返回1-100之间的随机数。或者请澄清你的问题。他需要模拟掷骰子。你最后一次看到有99张脸的骰子是什么时候?我以前见过有100张脸的骰子。@Slavic不幸的是,他们存在为什么不存在?1-100中的任何数字都有同等机会出现。或者至少在我看来是这样的,你将不得不采用一个楼层函数,你最后所得到的间隔,相对于整数之间的直线,空间是不均匀的。试着写下记号3,6,9,12,15。。。在一行上,然后勾选2,4,6,8,。。。你会明白我的意思。或者更确切地说,任何整数的组合(a,b,c,d,e,f)->一个数字1-100。你真的认为你能做到这一点吗?不这和原来的数学问题是一样的,浮点数法只是为了计算而绕道而行。有趣的是,这与斯莱维茨的答案类似,斯莱维茨的答案肯定是在我写这篇文章的同时写的,只是我用的是整数而不是小数。:)不需要括号,%运算符的优先级高于+。
    int total = 0;
    int[] diceRolls;
    for (int roll : diceRolls) {
        total = total*6 + roll - 1;
    }
    
    return total % 100 + 1;