2

我有一个程序,它大量使用随机数来决定它需要做什么,并且有许多基于 PRNG 输出的执行路径。在尝试调试它之后,我决定让所有 PRNG 调用都引用同一个 Random 实例,该实例在实例化时已被植入一个硬编码数字。这样,每次我运行程序时,都会出现相同的错误。不幸的是,每次运行它时我仍然会遇到不同的错误(尽管它的行为似乎几乎相同)。

我已经多次搜索代码以查找对 Math.random() 的任何未接来电,我向您保证没有。

有任何想法吗?

编辑:我已经确认生成的数字是相同的,但行为仍然是不确定的。这个程序不是多线程的。还是完全糊涂了。

所以 PRNG 的行为符合预期,但我仍然有不确定性。有哪些方式可能会无意中将非确定性带入程序中?

4

3 回答 3

3

好的,我我已经找到了我的非确定性来源。我有一次迭代了一个 HashSet。HashSet 会以相同的顺序填充相同的东西,但是因为我没有指定要添加到 HashSet 的类的散列方法,所以它将默认为某个散列,具体取决于每个实例的内存位置。

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

于 2012-05-21T22:52:39.980 回答
2

好的,所以这似乎是一种巫术。尝试创建一个自定义 PRNG,它包装一个Random对象并使用堆栈跟踪记录调用。

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 的每次调用,包括值和堆栈跟踪(如果您愿意,可以添加调用计数)。尝试运行您的应用程序几次,看看在哪个点(堆栈跟踪)出现分歧。

于 2012-05-21T13:37:55.073 回答
0

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

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