如何根据概率在Java中生成随机字母? [英] How do I generate random letters in java based on probability?

查看:128
本文介绍了如何根据概率在Java中生成随机字母?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法根据概率生成随机字母.

I am having trouble generating random letters based on probability.

例如,字母J,K,Q,Y,Z的出现概率均为1/96.其他字母也使用类似的过程(概率更高).

For example, the letters J, K, Q, Y, Z each have a probability of 1/96 of occurring. A similar process (with higher probabilities) is used for other letters.

有人可以告诉我该怎么做吗?

Can somebody show me how to do this?

具体我正在编写一种名为"getRandomLetter"的方法,该方法根据概率分数返回随机字母的字符.

Edit to be specific: I'm writing a method called "getRandomLetter" that returns a char of a random letter based on a probability fraction.

推荐答案

从具有特定概率的离散元素集中进行选择的典型方法是选择一个随机浮点数,并找出它所在的范围.会举例说明.假设您在三个字母A,B和C中进行选择,概率分别为0.255、0.407和0.338.您将计算一个介于0和1之间的随机数

The typical way to select from a discrete set of elements with specific probabilities is to choose a random floating-point number and find out which range it lies in. I'll explain with an example. Suppose that you're choosing among three letters, A, B, and C, with probabilities 0.255, 0.407, and 0.338 respectively. You would compute a random number between 0 and 1

double r = Math.random();

首先将其与0到0.255之间的范围进行比较:

and first compare it to the range from 0 to 0.255:

if (r < 0.255) {
    return 'A';
}

然后从0.255到(0.255 + 0.407)的范围:

then to the range from 0.255 to (0.255 + 0.407):

else if (r < 0.662) {
    return 'B';
}

,如果不是两者之一,则必须为'C':

and if it's not either of those, it has to be 'C':

else {
    return 'C';
}

如果使用字母的所有26个字母进行此操作,则写出if-else语句的所有26种情况将很痛苦.您可以预先准备一个字符数组及其各自的概率,

If you're doing this with all 26 letters of the alphabet, it will be a pain to write out all 26 cases of the if-else statement. What you could do in advance is prepare an array of the characters and their respective probabilities,

char[] chars = {'A', 'B', 'C', ...};
double[] probabilities = {0.01, 0.02, 0.05, ...};

,然后可以使用如下循环自动完成所有if:

and then you can automate all that if-ing with a loop like this:

double r = Math.random();
double cdf = 0.0;
for (int i = 0; i < chars.length; i++) {
    cdf += probabilities[i]
    if (r < cdf) {
        return chars[i];
    }
}
return chars[chars.length - 1];

在您的情况下,如果所有概率均为1/96的倍数,则可以选择小于96的随机整数而不是浮点数来执行相同的操作.只需使用int而不是double,然后使用rnd.nextInt(96)选择0到95(含)之间的整数,而不是Math.random().另外,您的probabilities数组将包含实际概率乘以96.

In your case, if all your probabilities are multiples of 1/96, then you can do the same thing choosing a random integer less than 96 instead of a floating-point number. Just use ints instead of doubles, and use rnd.nextInt(96) to choose an integer between 0 and 95, inclusive, instead of Math.random(). Also, your probabilities array would contain the actual probability times 96.

char[] chars = {'A', 'B', 'C', ...};
int[] probabilities = {5, 2, 4, ...}; // needs to sum to 96

// later...

int r = rnd.nextInt(96);
int cdf = 0;
for (int i = 0; i < chars.length; i++) {
    cdf += probabilities[i]
    if (r < cdf) {
        return chars[i];
    }
}
return chars[chars.length - 1];

现在,如果您正在做类似从袋子中绘制Scrabble瓷砖的操作,那么它将变得更加棘手,因为这是一个无需替换的采样过程,即,每次绘制后概率都会发生变化.我认为在这种情况下,一种更好的方法是实际使用一个集合来模拟袋子,然后为每个带有该字母的图块实际添加字母的一个副本.您仍然可以使用之前的相同charsprobabilities数组循环进行此操作:

Now, if you're doing something like drawing Scrabble tiles out of a bag, then it becomes trickier because that is a sampling process without replacement, i.e. the probabilities change after every draw. I think a better method in that case would be to actually use a collection to simulate the bag, and then actually add one copy of the letter for each tile that has that letter on it. You can still do this in a loop using the same chars and probabilities arrays from before:

char[] chars = {'A', 'B', 'C', ...};
int[] probabilities = {5, 2, 4, ...}; // number of tiles with each letter

LinkedList<Character> bag = new LinkedList<Character>();
for (int i = 0; i < chars.length; i++) {
    for (int n = 0; n < probabilities[i]; n++) {
        bag.add(chars[i]);
    }
}

然后,您可以bag.shuffle()随机划分图块,而bag.pop()则允许您随机选择一个.

Then you can bag.shuffle() to randomize the tiles, and bag.pop() lets you pick one at random.

这篇关于如何根据概率在Java中生成随机字母?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆