Java的随机数在长期运行中总是呈现负趋势吗?

11

我正在构建一个应用程序,为此我有一个填充测试数据的函数。 简要概述:

        HashMap<String, Long> iIDs = new HashMap<String, Long>();
        HashMap<String, Integer> vals = new HashMap<String, Integer>();

        long iID1 = addIndicator("I1", "i1", Color.RED);
        long iID2 = addIndicator("I2", "i2", Color.BLUE);
        long iID3 = addIndicator("I3", "i3", Color.GREEN);
        long iID4 = addIndicator("I4", "i4", Color.MAGENTA);

        iIDs.put("iID1", iID1);
        iIDs.put("iID2", iID2);
        iIDs.put("iID3", iID3);
        iIDs.put("iID4", iID4);

        int v1 = 80;
        int v2 = 30;
        int v3 = 25;
        int v4 = 40;

        vals.put("v1", v1);
        vals.put("v2", v2);
        vals.put("v3", v3);
        vals.put("v4", v4);

        int numDays = 500;
        int dateDistance = 14;

        Calendar c = Calendar.getInstance();

        for(int i=0;i<numDays;i++)
        {
            c.add(Calendar.DATE, dateDistance);
            for(int j=1;j<5;j++)
            {
                int currVal = vals.get("v"+j);
                int rand = new Random().nextInt(6);
                int newVal; 

                if(rand <= 2) // 0, 1, 2
                    newVal = currVal + rand;
                else          // 3, 4, 5
                    newVal = currVal - rand;

                pseudo: addPointForIndicator();
                vals.put("v"+j, newVal);
            }
        }
无论我创建测试数据的频率如何,图像看起来总是这样:Graph 因此,随机数的趋势总是负的。为什么会这样?

2
为什么你在每个循环迭代中都创建一个新的 Random 对象? - Baz
1
并不是说这一定能解释你的结果,但是你使用 Random 的方式是错误的。你必须在所有调用中共享相同的实例,否则你得到的不是一个伪随机序列。 - Marko Topolnik
使用同一个 java.util.Random 实例来生成所有随机数。这将通过使随机化成为真正的伪随机化来“增加随机化”。 - FThompson
谢谢,现在我已经在第一个for循环上面创建了Random,但是像你说的那样,图片没有改变。我只是想知道... - Toni Kanoni
3个回答

6

从你的逻辑中很清楚,即使忽略你对Random的使用不符合合同的事实,它也必须产生负面趋势。你一半的时间在范围[0,2]内加一个数字,另一半时间在范围[3,5]内减去一个数字。代码很容易修复,只需要:

if(rand <= 2) // 0, 1, 2
  newVal = currVal + rand;
else          // 3, 4, 5
  newVal = currVal - rand + 3;

一个更好的修复方案是

newVal = currVal + random.nextInt(7)-3;

这样做的另一个好处是,有时候它可以让值保持不变,这样可以更好地模拟数据。

哈哈,你说得对... :) 啊,逻辑,我的敌人... 谢谢!我会在5分钟内将你的帖子标记为答案。 - Toni Kanoni
2
下投票者,你为什么要对这个完美的、被接受的答案进行负评?这绝对是恶意破坏,而且是最遗憾的一种——躲在匿名背后。 - Marko Topolnik

2
我不确定你想做什么,但以下代码块似乎会产生负面趋势。
if(rand <= 2) // 0, 1, 2
    newVal = currVal + rand;
else          // 3, 4, 5
    newVal = currVal - rand;

你正在进行小数相加和大数相减的操作。

对,Marko Topolnik 刚带我来看这个……有时最明显的东西却是最难被发现的 :P - Toni Kanoni

0

我不知道你的目的是什么,但是尝试设定一个下限。比如

2+random.nextInt()

其中 random 是您的 Random 类实例。正如其他人所说,使用相同的实例,否则您无法生成“正确”的序列。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接