随机某种种子似乎仍然是随机的

时间:2012-05-21 13:01:32

标签: java random prng

我有一个程序,它大量使用随机数来决定它需要做什么,并且根据PRNG的输出有许多执行路径。拔出我的头发试图调试之后,我决定让所有PRNG调用引用相同的Random实例,在实例化时将其播种到硬编码的数字。这样,每次运行程序时,都会出现相同的错误。 不幸的是,每次运行它时我仍会得到不同的错误(尽管它看起来几乎一样)。

我对Math.random()的任何错过调用多次搜索过代码,我向你保证没有。

有什么想法吗?

编辑:我已确认生成的数字是相同的,但行为仍然是不确定的。该程序不是多线程的。仍然完全不知所措。

所以PRNG表现得像预期的那样,但我仍然有非决定论。非决定论可能会无意中被纳入某个计划的方式有哪些?

3 个答案:

答案 0 :(得分:3)

好的,我认为我找到了我的非决定论的来源。我一度迭代HashSet。 HashSet会以相同的顺序填充相同的东西,但由于我没有指定要添加到HashSet的类的哈希方法,因此根据每个实例的内存位置,它将默认为某些哈希值。 / p>

将HashSet的每个实例更改为LinkedHashSet 似乎为我提供了大约30次运行的一致结果,之前它只能连续几次给我相同的行为。

答案 1 :(得分:2)

好的,所以这看起来像伏都教。尝试创建一个包装Random对象的自定义PRNG,并使用stacktraces记录调用。

public class CustomRNG {

    private static Logger logger = Logger.getLogger(CustomRNG.class.getName());
    private static Random random = new Random(1234);

    public int nextInt() {

       int val = random.nextInt();
       log(val);

       return val;
    }

    private void log(int value) {
        logger.log(Level.INFO, "value: " + value, new Throwable());
    }
}

这会记录对nextInt的每次调用,包括值和堆栈跟踪(如果你愿意,可以添加调用计数)。 尝试运行你的应用程序几次,看看它在哪个点(堆栈跟踪)发散。

答案 2 :(得分:1)

持续不确定性的可能原因(按可能性的降序排列):

  • 您尚未使用相同的随机实例替换所有 PRNG调用。你可能想先检查一下:-)一个好的IDE应该可以帮助你找到对Random类的所有引用。
  • 由并发引起的时间效应(例如,哪个线程首先调用PRNG很重要)
  • 您在系统中有某种形式的外部输入(例如用户输入?基于系统计时器的操作?)
  • 您正在使用的某个库有一个非确定性元素,它影响程序的行为(例如,某些排序算法使用的随机数会影响它们返回的结果的排序)
  • 您正在遇到某种环境约束(例如,有时会发生OutOfMemoryError或IOException错误,但会以不同方式捕获和恢复,或者GC决定清除某些软/弱引用)
  • 摧毁记忆的宇宙射线/硬件错误