这可能是一个奇怪的问题,但在这里:
我有一个数值模拟。这不是一个特别长的计划,但有点冗长来解释它正在做什么。我运行模拟一千次计算平均结果和方差,方差非常小,大约为10 ^( - 30)。
然而,我注意到当我在python 3.3中运行程序时,事情变得奇怪了。参见Python 2.7和Python 3.2我每次都会得到相同的答案。相同的平均值,相同的微小差异。
但是当我在Python 3.3中运行它时,我每次都会得到一个不同的答案。也就是说,不同的平均值和不同(但仍然很小)的差异。这是非常奇怪的,因为概率定律说如果方差实际上很小就不会发生这种情况。所以我想知道,自3.2以来改变的3.3解释器到底发生了什么,这导致我的模拟变得疯狂?
以下是我想到的一些事情:
是否有人指出可能导致我出现问题的从3.2变为3.3的内容?
答案 0 :(得分:9)
你的最后一个要点很可能是原因。在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,因此您可以使用它来测试我们的假设。
答案 1 :(得分:3)
设置环境变量
PYTHONHASHSEED
到0,看看是否有帮助(这样可以省去通过mgilson给你的链接挖掘麻烦;-))。
但请注意,没有任何永远定义了遍历字典的顺序。要获得真正可重现的结果,您需要强制执行自己的订单。例如,使用
会有任何实际问题sorted(table)
代替?然后你可以不再担心32位与64位,哈希随机化,未来错误修正改变顺序等等。