2012-09-10 55 views
0

我无法根据概率生成随机字母。如何根据概率在java中生成随机字母?

例如,字母J,K,Q,Y,Z各自具有发生1/96的概率。其他字母使用类似的过程(具有更高的概率)。

有人可以告诉我如何做到这一点?

编辑是特定的:我正在写一个名为“getRandomLetter”的方法,它根据概率分数返回一个随机字母的字符。

+0

你想要的只是一个返回随机选择的字母的方法?或者一串呢?还是数组?请具体说明你想要做什么。 –

+2

很多方法。你有尝试过什么吗?你想吐出随机字母能够设置不同的概率每个字母? –

回答

1

Here's some documentation on generating random numbers in java.

现在,让我们说你产生

,那么你可以在每个你的信映射到这些号码中的一个0和95包容性(96可能的变体)之间的随机整数。一个简单的和肮脏的方式做这将是一个switch语句

switch (randomNumber) 
{ 
    case 0: 
     //decide that you want J 
    break; 
    case 1: 
    case 2: 
     // maybe you want a letter to have a 2/96 probability 
    break; 
} 

另一种简单的方法来做到这一点是使用字符数组。

Random rand = new Random(new Date().getTime()) 
char[] charArray = {'A','B','C','C','D','E','F','F','F'}; 
char chosenChar = charArray[rand.nextInt(0, 96)]; 
+0

我需要制造96个开关盒吗?有没有更干净的方法呢? –

+0

@MattM我刚刚抢先编辑我的帖子,建议制作一个字符数组。 –

+0

@MattM无论你做什么,你都必须发表大量的陈述来给出每封信的概率。 –

0

你可以做的是这样的:

List<char> letters = new List<char>(); 
Dictionary<int,List<char>> set1 = new Dictionary<int,List<char>>(); 
set1.Key = 2; 
set1.Value = new List<char>{'A','B'} //blah blah blah 

使这些字典的数组或列表和foreach他们

foreach (char theChar in set1.Value) 
{ 
    for (int i = 0; i < set1.Key;i++) 
    { 
    letters.add(theChar); 
    } 

然后,

Random random = new Random(); 
char nextchar = letters[random.nextInt(letters.Count - 1)]; 

你想要的时间越多要被选中,你在列表中添加的次数就越多。

ALSO:如果需要,可以用一个长度的字符串替换字符。

编辑:这里是旧的方式添加到字母:

for (int i = 0; i < 4; i++) // 4 times 
{ 
    letters.add('a'); 
} 
for (int i = 0; i < 3; i++) // 4 times 
{ 
    letters.add('b'); 
} 

+0

我喜欢你的想法,但是如果我将这些字母分组到数组中,是否有办法做到这一点?像char [] set1 = {J,K,Q,Y,Z},然后给他们每个人一个1/96的重量? –

+0

@MTM - 尝试你在我的答案中看到的内容 - 字典中的关键字代表重量,并且该值代表具有该重量的字符 – tehdoommarine

3

典型的方法,从一组离散的具有特定概率元素的选择是选择一个随机的浮点数并找出它所在的范围。我将用一个例子来解释。假设你在三个字母中选择A,B和C,其概率分别为0.255,0.407和0.338。你将计算的随机数0和1之间

double r = Math.random(); 

和第一比较它的范围从0到0.255:然后

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

从0.255至(0.255 + 0的范围内。407):

​​

,如果它不是这类原因,它必须是'C'

else { 
    return 'C'; 
} 

如果你以字母表中所有26个字母这样做,这将是一个痛苦写出所有26个案例的if - else声明。你可以事先做的准备是角色以及他们各自概率的数组,

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

,然后你可以自动所有if用这样的循环-ing:

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 s而不是double s,并使用rnd.nextInt(96)来选择0和95之间的整数,而不是Math.random()。此外,您probabilities阵列将包含实际的概率时间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]; 

现在,如果你正在做一些喜欢绘画拼字游戏瓷砖从包里拿出来,然后就变得棘手,因为这是一个采样过程,无需更换,即每次抽签后概率都会改变。我认为在这种情况下更好的方法是实际使用一个集合来模拟包,然后为每个包含该字母的图块添加一个字母副本。您仍然可以使用相同的charsprobabilities阵列从之前这样做在一个循环:

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()让你随机挑选一个。

0

最简单的解决方案将需要一个紧凑的容器给定字母的出现概率。我建议使用可用作概率函数的HashMap(离散分布函数)。就像这样:

HashMap<Character, Double> map = new HashMap<Character, Double>(); 
for(Character c : {'J', 'K', 'Q', 'Y', 'Z'}) { 
    map.put(c, 1.0/96.0); 
} 
// and so on 

对于起见,将是很好的确保,所有概率的整体之和等于1.0,但数字可以被视为概率weigths和标准化的结尾。你明白了吧?

一个纯粹的数学问题需要创建一个累积分布函数,恢复它,然后使用该函数进行解释。这样你就可以提供一个以几乎任何概率分布生成任意随机值的解决方案。

让我们尝试做一次:

double sum = 0.0, partialSum = 0.0; 
HashMap<Double, Character> dist = new HashMap<Double, Character>(); 
for(Entry<Character, Double> entry : map.entrySet()) { 
    sum += entry.getValue(); // for normalization purpose, if you are really sure 
    // that all the probabilities sum up to 1.0, then the first loop is redundant 
} 
for(Map.Entry<Character, Double> entry : map.entrySet()) { 
    dist.put(partialSum/sum, entry.getKey()); 
    partialSum += entry.getValue(); // the cumulative probability here 
} 

现在使用地图只是调用

Random r = new Random(); 
... 
dist.get(r.nextDouble());