2012-09-10 95 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());