Android: random number is not very random

故事扮演 提交于 2020-12-12 10:13:05

问题


I am writing a word-learning application for android.

To get random word I use:

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

To get random direction (show word or show translation) I use:

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

But I see, that a words are not uniformly distributed. I'm testing the application with 17 words. Some words are shown 10 times, some are shown only once. The same problem is with direction. It often happens, for the fifth consecutive time direction is the same.

Maybe someone know, how to make distribution of words more equal?

UPD: I've written a test application. It generates new number on button click:

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);
  }
}

Here are the test results:enter image description here

Maybe, with N=10000 it will be equal... But for my application it's a poor consolation.


回答1:


What you do should give you very well uniform pseudo-random distribution.
You could run you sampling for, say, 1000 times and count how often each results appears in the end. It should be approximately same. Otherwise, please post more code causing problems.

Update To convince yourself, try running simple test below on your platform and check observed results. The bigger testNum the more uniform result you will get.

        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  + "%");
        }



回答2:


Don't use

Random rnd = new Random();

each time you want a number. Make rnd a wider scoped variable(instance, class, etc) and just run that once to initialize it.

Then you just use

int whatever = rnd.nextInt(WordsNumber);

when you want a new number.

When you create a new Random(), it initializes a new PRNG with the seed set to current time. If the time hasn't changed since the last time you called it, you'll get the same number sequence.




回答3:


A shuffling algorithm, proposed by Geobits is good solution.

But it is more simple way. I've decided to make array of recent words. Store 6-8 last words is enough for fixing this problem.



来源:https://stackoverflow.com/questions/19732456/android-random-number-is-not-very-random

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!