2013-11-01 9 views
3

Я пишу приложение для изучения английского языка для Android.Android: случайное число не очень случайное

Чтобы получить случайное слово я использую:

Random rnd = new Random(); 
final int rnd.nextInt(WordsNumber); 

Чтобы получить случайное направление (показать слово или показать перевод) Я использую:

Random rnd = new Random(); 
final boolean dir.nextBoolean(); 

Но я вижу, что через слова не распределены равномерно , Я тестирую приложение с 17 словами. Несколько слов показаны 10 раз, некоторые показаны только один раз. Такая же проблема с направлением. Это часто случается, так как пятое последовательное временное направление одно и то же.

Возможно, кто-то знает, как сделать распределение слов более равным?

UPD: Я написал тестовое приложение. Он генерирует новый номер на нажатии кнопки:

public class About extends Activity 
{ 
    final int N = 10; 
    int[] results; 
    Random rnd; 
    int total; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_about); 

    results = new int[N]; 
    for (int i = 0; i < N; i++) 
    { 
     results[i] = 0; 
    } 

    rnd = new Random(); 
    total = 0; 
    } 

    public void GenerateNumber(View view) 
    { 
    int number = rnd.nextInt(N); 
    results[number]++; 
    total++; 

    String output = new String(); 
    TextView txt = (TextView)findViewById(R.id.text1); 

    output += "Total numbers: " + String.valueOf(total) + "\n"; 
    for (int i = 0; i < N; i++) 
    { 
     output += String.valueOf(i) + ": " + String.valueOf(results[i]) + "\n"; 
    } 
    txt.setText(output); 
    } 
} 

Вот результаты теста: enter image description here

Может быть, с N = 10000 она будет равна ... Но для моего приложения, это слабое утешение.

+4

Скорее всего, это связано с эквивалентом Java [C# - генератор случайных чисел, генерирующий только одно случайное число] (http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number/768001 # 768001) –

+4

Напоминает мне об этом [http://xkcd.com/221/) один ... – tilpner

+0

@StackOverflowException Сэр, ты сделал свой день. –

ответ

0

A shuffling algorithm, предложенный Geobits, является хорошим решением.

Но это более простой способ. Я решил сделать массив последних слов. Хранить 6-8 последних слов достаточно для устранения этой проблемы.

2

То, что вы делаете, должно дать вам очень хорошее равномерное псевдослучайное распределение.
Вы можете запустить выборку, скажем, 1000 раз и подсчитать, как часто каждый результат появляется в конце. Он должен быть примерно таким же. В противном случае, пожалуйста, напишите больше кода, вызывающего проблемы.

Обновление Чтобы убедиться в этом, попробуйте выполнить простой тест ниже на своей платформе и проверить полученные результаты. Чем больше testNum, тем более общий результат вы получите.

 final int testNum = 10000; 
     final int max = 9; // will generate integers in range [0 ; 9] 
     Random rnd = new Random(); 
     int[] results = new int[max + 1]; 

     for (int i = 0; i < testNum; ++i) { 
      int nextRandomNumber = rnd.nextInt(max + 1); 
      results[nextRandomNumber]++; 
     } 

     // print statistics 
     System.out.println("tests performed = " + testNum); 
     for (int i = 0; i <= max; ++i) { 
      System.out.println("frequency of " + i + " is " 
       + results[i] * 100/testNum + "%"); 
     } 
+0

Да, вы правы, он должен! Но, похоже, что класс Random() класса больше нравится другим. – vitperov

+0

@vitperov Попробуйте запустить код выше и опубликовать результаты. Он должен быть однородным. – kiruwka

+0

Спасибо за советы. Я проверю его позже. – vitperov

0

Прежде всего, вы можете проверить этот вопрос:

Getting random numbers in Java

и, возможно, проверить Math.random класс.

Во-вторых, на небольшом диапазоне выборок случайный может вернуть один номер больше других. Но с достаточно большой тестовой шкалой он должен распространяться более равномерно.

+0

Я раньше использовал 'Math.random'. Ситуация такая же – vitperov

2

Не используйте

Random rnd = new Random(); 

каждый раз, когда вы хотите номер. Сделайте rnd более широкую переменную (экземпляр, класс и т. Д.) И просто запустите ее один раз, чтобы инициализировать ее.

Тогда вы просто использовать

int whatever = rnd.nextInt(WordsNumber); 

, когда вы хотите новый номер.

Когда вы создаете new Random(), он инициализирует новый PRNG с установленным временем семян текущим временем. Если время не изменилось с момента последнего вызова, вы получите такую ​​же последовательность чисел.

+0

Спасибо за идею, но она ничего не меняет. – vitperov

+2

Если вы используете только несколько итераций, это будет выглядеть так, как будто это не случайность во многих случаях. Люди - очень плохие судьи случайности. Если вы просто хотите, чтобы слова отображались более равномерно, вы можете захотеть рассмотреть [алгоритм перетасовки] (http://en.wikipedia.org/wiki/Knuth_shuffle). Это даст вам все ваши варианты, прежде чем повторять их. – Geobits

Смежные вопросы