使用一对六面骰子以[1,4]不均匀生成随机数的最有效方法是:在40%的时间内产生1,在30%中产生2,在20%中产生3和10%中的4%。
请证明方法的正确性并给出算法。
骰子可能有不同的颜色。
注意:唯一可用的随机数发生器是两个颜色不同的六面骰子。
答案 0 :(得分:8)
假设两个骰子:一个白色骰子。
现在你有你需要的东西:
您需要的不是4种可能的结果,而是10种因为它可以代表您想要的加权结果。两个骰子可以通过多种方式产生36种可能性,但你需要的是10或10的倍数,如上所述。
这种方法的唯一缺点是它是概率性的(意味着你可以在技术上永远地重新定位31+),但我不相信存在确定性和准确的解决方案。
答案 1 :(得分:2)
关键:“它应该在40%的时间内产生1%,2%在30%,3%在20%,4%在10%”
一对6面骰子有36种可能的结果。
红色,蓝色(假设有一些骰子的区别)
1 1
1 2
1 3
1 4
1 5
1 6
2 1
2 2
2 3
2 4
2 5
2 6
3 1
3 2
3 3
3 4
3 5
3 6
4 1
4 2
4 3
4 4
4 5
4 6
5 1
5 2
5 3
5 4
5 5
5 6
6 1
6 2
6 3
6 4
6 5
6 6
36个结果中有10%分解为3.6个结果......这是不可能的,所以你要抛出六个结果来得到30个结果,这个结果可以除以10.为了方便起见,抛弃重复的角色( 1-1,2-2,3-3,4-4,5-5,6-6)
现在,如果有3个结果,则为10%的单位。现在你的垃圾箱[1-4]需要适当数量的结果来弥补40%,30%,20%,10%。
..或
40%= 12/30结果...所以采取前12个案例..记住重复删除=(1,2)到(3,2)
30%= 9/30结果......接下来的9个结果=(3,4)到(5,1)
20%= 6/30结果......接下来的6个结果=(5,2)到(6,2)
10%= 3/30结果......取最后3个结果=(6,3)到(6,5)
..现在的问题是,任何重复的滚动都会强制重新滚动,这可能会反复发生,所以效率不高。问题是基础6(骰子)和基础10(10%= 1/10)是缺乏一个更好的术语 - 相互补充。这与二进制中表示1/10的问题相同。无论您使用多少钻头,您都只能靠近=无论有多少卷,您都无法使用6面模具生产出完美的10%垃圾箱。
你必须使用5或10面死。
答案 2 :(得分:2)
正如其他人所指出的那样,没有一种解决方案可以100%有效地工作,你必须使用拒绝抽样。
一般来说,我是第二个Cletus的答案,但是使用他的算法,你将从两个骰子获得一个概率为5/6的结果,这意味着预期的“每个骰子的结果数”是5/12~ = 0.417。将后者乘以你的一个随机结果的熵,
-(0.1*log2(0.1) + 0.2*log2(0.2) + 0.3*log2(0.3) + 0.4*log2(0.4)) ~= 1.846
我们获得0.770。换句话说,我们平均每个芯片使用0.770位信息。我们可以比这更好。
例如,投掷9个骰子,你有6 ^ 9 = 10077696可能的结果。在Cletus之后,形成一个从0到10077695的数字,并且只有在介于0和9999999之间时才保留它(这种情况发生的概率为~0.992)。在这种情况下,你有7个随机十进制数字,均匀分布,你可以从你的问题中提取一个随机数:
0,1,2,3 --> 1
4,5,6 --> 2
7,8 --> 3
9 --> 4
这样,我们每9个骰子有7个随机结果,概率为0.992,或平均“每个骰子的结果数”为0.992 * 7 / 9~ = 0.772。将其乘以结果的熵,我们得到1.846 * 0.772~ = 1.425。因此,通过这种方式,我们平均每个芯片使用1.425位。
我们可能会更好地投掷更多骰子或采用其他技术。当然,上限是骰子的熵,即log2(6)〜= 2.585位。
答案 3 :(得分:1)
一种方法是生成一个随机整数,并将其用作指定概率的数组的索引。
例如,以下的伪代码将产生1 2 / 3rds的时间,以及2 1/3的时间。
var randArray = [1, 1, 2];
var randIndex = random(2);
return randArray[randIndex];
答案 4 :(得分:1)
我做其他人的作业感觉不太好,但我可以给出一个提示:看看this graph并从那里开始工作。
答案 5 :(得分:1)
这是我为biased roulette wheel for a genetic algorithm编写的一个骰子,但可以进行调整。它位于C#中,但很容易更改为Java或其他基于C语言。
首先从一组值开始
如果要复制实际骰子,请将这些值换成数字1-6。
double[] values =
{
9,
66,
153,
2,
42,
34
};
然后添加您希望每个百分比显示的百分比 例如,您希望153有偏差,因此在25%的时间内选择它:
double[] percentages =
{
15,
10,
25,
5,
37,
8
};
现在设置一些百分比范围。
这用于掷骰子,所以如果滚动15-25,你知道它落在第二个百分比范围内。
double[] ranges = new double[6];
ranges[0] = percentages[0];
ranges[1] = ranges[0] + percentages[1];
ranges[2] = ranges[1] + percentages[2];
ranges[3] = ranges[2] + percentages[3];
ranges[4] = ranges[3] + percentages[4];
ranges[5] = ranges[4] + percentages[5];
最后,生成一个随机数。
如果该数字落在其中一个范围之间,请从值中选择该索引。
static Random _random = new Random();
static void Main(string[] args)
{
...
for (int i = 0; i < percentages.Length; i++)
{
int rand = _random.Next(0, 100);
double x = ranges.First(n => n >= rand);
int index = ranges.ToList().IndexOf(x);
Console.WriteLine(values[index]);
}
}
我确信有办法改善这一点,我很想知道它们。
答案 6 :(得分:0)
使用标记为1,1,1,1,2,2,2,3,3,4的10面模具。或者你(由于某种原因)限于六面骰子?有关计算机实现,请参阅Benny Jobigan的回答。
但是,如果你只限制两个六面骰子,一种方法是制作36张小方卡。标记12标记为“1”,标记9标记为“3”,标记3标记为“4”,标记3标记为空白或标记为“重新翻滚”。
将36张卡片放在一个6x6的方格中。使用数字1-6标记每一行和每列,并确定哪些模具对应于列以及哪些行。
掷骰子,找到与所选行和列对应的卡片。如果卡上有一个号码,那就是你想要的号码,如果它是空白的(或说“重新滚动”),再次掷骰子。
请注意,网格上数字的确切位置对于公平骰子无关紧要,但对于有偏见的骰子会给出不同的结果。
答案 7 :(得分:0)
由于此作业可能已经过时,我会给出答案:我们的想法是逐步完善你的卷,直到你可以确定选择了哪种颜色。
首先,将范围从0到1划分为与概率相对应的块:在数字线上标记0.4,0.7,0.9和1.0,它们定义标记为1到4的区域。您需要跟踪数字你掷骰子的时间,n和跑步的计数器,p。最初,设置n = 1,p = 0。
这样一来,大多数时候你只需要一两卷来确定选择哪种颜色,尽管如果你最终靠近边界,你将不得不滚动更多。使用你的重量,40%的时间你只需要1次滚动,44%的时间你需要2次,13%你需要3次,大约3%的时间你需要更多。