这可能是一个奇怪的问题,但问题是:
我有一个数值模拟。这不是一个特别长的程序,但解释它在做什么有点冗长。我正在运行模拟一千次并计算平均结果和方差,方差非常小,大约为 10^(-30)。
但是,我注意到当我在 python 3.3 中运行程序时,事情变得很奇怪。在 Python 2.7 和 Python 3.2 中看到,每次我总是得到相同的答案。相同的平均值,相同的微小差异。
但是当我在 Python 3.3 中运行它时,我每次都会得到一个不同的答案。也就是说,不同的平均值和不同的(但仍然很小)方差。这非常奇怪,因为概率法则表明,如果方差真的那么小,就不会发生这种情况。所以我想知道,自 3.2 以来发生变化的 3.3 解释器到底发生了什么,导致我的模拟变得疯狂?
以下是我想到的一些事情:
- 我的 Python 版本可能存在奇怪的 32 位/64 位差异,但没有,我检查过它们都运行 64 位。
- 我可能在 float/int 转换中遇到了一些错误,但这会在 Python 3.2 中得到解决,因为它们在适当的时候使除法返回 float ,所以 3.2 和 3.3 的结果应该是相同的。
- 我的模拟被表示为生成器,所以可能 3.3 中的生成器发生了一些变化,但我不知道那是什么。
- 数字浮点表示有一些我不知道的变化。
- 结果为“未确定”的其中一个函数存在一些潜在的变化,这会影响我的算法的初始条件。例如,在我的代码中的某处,我使用“list(table.keys())”对我的数据列进行排序,这些数据列最初是一个字典,并且 list 决定将字典键从 3.2 排序到 3.3 的方式可能发生了变化。但如果是这种情况,那么代码仍然应该每次都做同样的事情,但事实并非如此(故意使列表随机排序似乎很奇怪!)。
有没有人指出从 3.2 到 3.3 的变化可能会导致我的问题?
最佳答案
您的最后一个要点很可能是原因。在 python3.3 ,默认情况下启用哈希随机化以解决安全问题。基本上,这个想法是您现在永远不知道您的字符串将如何散列(这决定了它们在字典中的顺序)。
这是一个演示:
d = {"a": 1, "b": 2, "c": 3}
print(d)
在我的机器上,使用 python3.4,这会产生 3 个不同顺序的结果:
$ python3.4 test.py
{'a': 1, 'c': 3, 'b': 2}
$ python3.4 test.py
{'c': 3, 'b': 2, 'a': 1}
$ python3.4 test.py
{'b': 2, 'c': 3, 'a': 1}
在散列随机化之前,如果您知道一个字符串将如何散列,那么对您的应用程序有足够了解的恶意攻击者可以为其提供数据,以导致字典查找在 O(n) 时间内运行,而不是通常的 O(1)字典查找。这可能会导致某些应用程序的性能严重下降。
您可以按照文档 here 禁用哈希随机化.在某些时候,他们还向 python 引入了一个 -R
标志,它在“选择加入”的基础上启用了哈希随机化。此选项至少适用于 python3.2,因此您可以使用它来检验我们的假设。
关于python - 在 Python 3.2 和 3.3 中给出不同结果的数值模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20416337/