【问题标题】:Android: random number is not very randomAndroid:随机数不是很随机
【发布时间】:2013-11-12 23:45:33
【问题描述】:

我正在为 android 编写一个单词学习应用程序。

为了得到我使用的随机词:

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

为了获得随机方向(显示单词或显示翻译),我使用:

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

但是我明白了,a 单词不是均匀分布的。 我正在用 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);
  }
}

测试结果如下:

也许,当 N=10000 时,它会相等...但对于我的应用程序来说,这是一个糟糕的安慰。

【问题讨论】:

  • 很可能是由 Java 等效的 C# - Random number generator only generating one random number 引起的
  • 让我想起了this 一个...
  • 您多久运行一次测试?重复说同样的话可能只是运气不好。除此之外,它可能是一些意外编程的偏差。
  • 您能否发布:a/ 实际代码和 b/ 实际结果(包括数字和所有内容)以验证/支持您的印象?
  • final int rnd.nextInt(WordsNumber); 在按钮点击时被调用。好的,我会写一个测试,但稍晚一点(星期一)。

标签: java android random


【解决方案1】:

你所做的应该会给你非常均匀的伪随机分布。
您可以进行 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  + "%");
        }

【讨论】:

  • 是的,你是对的,应该!但看起来,特定数字 Random() 类比其他数字更喜欢。
  • @vitperov 尝试运行上面的代码并发布你的结果。它应该是统一的。
  • 感谢您的建议。稍后我会测试它。
【解决方案2】:

不要使用

Random rnd = new Random();

每次你想要一个数字。使rnd 成为范围更广的变量(实例、类等),然后运行一次即可对其进行初始化。

那你就用

int whatever = rnd.nextInt(WordsNumber);

当你想要一个新号码时。

当您创建 new Random() 时,它会初始化一个新的 PRNG,并将种子设置为当前时间。如果自上次调用以来时间没有改变,您将获得相同的数字序列。

【讨论】:

  • 感谢您的想法,但它不会改变任何东西。
  • 如果您只运行几次迭代,那么在很多情况下,它会看起来看起来不是随机的。人类对随机性的判断力非常差。如果您只想让单词显示得更统一,您可能需要考虑使用shuffling algorithm。这将为您提供所有选项一次,然后再重复任何选项。
【解决方案3】:

Geobits 提出的shuffling algorithm 是很好的解决方案。

但这是更简单的方法。 我决定做一些最近的话。存储 6-8 个遗言就足以解决此问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-04
    • 2013-04-03
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    • 2014-04-27
    • 2015-09-10
    相关资源
    最近更新 更多