2013-11-01 125 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

让我想起[this](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