Python浮点确定性

Posted

技术标签:

【中文标题】Python浮点确定性【英文标题】:Python floating point determinism 【发布时间】:2014-02-08 06:25:37 【问题描述】:

下面的代码(用于计算余弦相似度)在我的计算机上重复运行时,将输出 1.0、0.9999999999999998 或 1.0000000000000002。当我取出 normalize 函数时,它只会返回 1.0。我认为浮点运算应该是确定性的。如果每次都对同一台计算机上的相同数据应用相同的操作,会导致我的程序出现这种情况的原因是什么?这可能与堆栈上调用 normalize 函数的位置有关吗?我怎样才能防止这种情况发生?

#! /usr/bin/env python3

import math

def normalize(vector):
    sum = 0
    for key in vector.keys():
        sum += vector[key]**2
    sum = math.sqrt(sum)
    for key in vector.keys():
        vector[key] = vector[key]/sum
    return vector

dict1 = normalize("a":3, "b":4, "c":42)
dict2 = dict1

n_grams = list(list(dict1.keys()) + list(dict2.keys()))
numerator = 0
denom1 = 0
denom2 = 0

for n_gram in n_grams:
    numerator += dict1[n_gram] * dict2[n_gram]
    denom1 += dict1[n_gram]**2
    denom2 += dict2[n_gram]**2

print(numerator/(math.sqrt(denom1)*math.sqrt(denom2)))

【问题讨论】:

【参考方案1】:

浮点数学可能是确定性的,但字典键的顺序不是。

当您调用.keys() 时,结果列表的顺序可能是随机的。

因此,循环内的数学运算的顺序也可能是随机的,因此结果不会是确定性的,因为虽然任何 浮点运算可能是确定性的,但结果一系列操作非常依赖于排序。

您可以通过对密钥列表进行排序来强制执行一致的顺序。

【讨论】:

字典的顺序仅在 Python 3.x 中是不确定的,除非在 Python 2.x 中明确配置 那么,您会建议执行命令,还是将其保留在“浮点数不精确,哦,好吧?”的类别中?我要做的就是观察这些数据。如果这些数据将用于进一步的计算,你会改变你的答案吗? 我通常会把它留在“浮点数不精确”领域。

以上是关于Python浮点确定性的主要内容,如果未能解决你的问题,请参考以下文章

什么定义了python中的浮点精度?

浮点非确定性的原因?包括 NumPy?

熊猫浮点错误

F# 在非确定性浮点计算方面是不是受到相同的 C# 警告?

可靠地确定浮点值向量是不是(数字上)等距

汇编浮点指令