3

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.

vitperov
  • 1,347
  • 17
  • 20
  • 4
    Most likely caused by Java equivalent of [C# - Random number generator only generating one random number](http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number/768001#768001) – Alexei Levenkov Nov 01 '13 at 17:58
  • 4
    Reminds me of [this](http://xkcd.com/221/) one... – tilpner Nov 01 '13 at 17:58
  • How often did you run your tests? It could be just bad luck that you got the same words repeatedly. Other than that it may be some accidentally programmed bias. – tiguchi Nov 01 '13 at 18:00
  • can you post : a/ actual code and b/ actual results (with numbers and all) to verify/support your impression ? – njzk2 Nov 01 '13 at 18:31
  • `final int rnd.nextInt(WordsNumber);` is called on button click. ok, I'll write a test, but a little bit later (on Monday). – vitperov Nov 02 '13 at 17:17
  • actually, no RNG will generate a *perfectly* uniform result set, because, well, duh, it's *random*. –  Jun 05 '14 at 14:48
  • It's known computing limitation https://en.wikipedia.org/wiki/Hardware_random_number_generator – user1742529 Apr 12 '21 at 05:59

3 Answers3

2

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  + "%");
        }
kiruwka
  • 9,250
  • 4
  • 30
  • 41
1

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.

Geobits
  • 22,218
  • 6
  • 59
  • 103
  • Thank you for the idea, but it doesn't change anything. – vitperov Nov 04 '13 at 15:01
  • 2
    If you're only running a few iterations, it's going to *look* like it's not random in a lot of cases. Humans are very bad judges of randomness. If you just want the words to show up more uniformly, you might want to consider a [shuffling algorithm](http://en.wikipedia.org/wiki/Knuth_shuffle) instead. This will give you all of your options once before repeating any. – Geobits Nov 04 '13 at 15:10
0

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.

vitperov
  • 1,347
  • 17
  • 20