数值模拟在Python 3.2和3.3中给出了不同的结果

时间:2013-12-06 05:00:32

标签: python python-3.x numerical-methods

这可能是一个奇怪的问题,但在这里:

我有一个数值模拟。这不是一个特别长的计划,但有点冗长来解释它正在做什么。我运行模拟一千次计算平均结果和方差,方差非常小,大约为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中得到解决,因为它们在适当时使得返回浮点值,所以3.2和3.3的结果应该是相同的。
  • 我的模拟被表示为生成器,因此可能会在3.3中使用生成器进行更改,但我无法分辨它是什么。
  • 我不知道数值浮点表示有一些变化。
  • 其中一个函数中存在一些潜在的变化,其结果是“未确定的”,这会影响我的算法的初始条件。例如,在我的代码中的某处,我使用“list(table.keys())命令我的数据列最初是一个字典”,并且列表决定如何从3.2到3.3排序字典键可能有所改变。但如果是这种情况,那么代码每次都应该做同样的事情,但事实并非如此(故意使列表的排序随机变得非常奇怪!)。

是否有人指出可能导致我出现问题的从3.2变为3.3的内容?

2 个答案:

答案 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位,哈希随机化,未来错误修正改变顺序等等。