如何保持float / double算术的确定性?

时间:2017-10-17 17:44:58

标签: python c precision floating-accuracy

如果我们使用具有double和float算法的算法,我们如何保证在x86和x64 Linux和Windows计算机以及ARM微控制器中在Python和C中运行它的结果相同?

我们使用的算法使用:

  • double + double
  • double + float
  • double exp(double)
  • float * float

在同一台计算机上,为x86和x64 MinGW编译它会得到不同的结果。该算法进行了大量的数学计算,因此任何小错误都会最终产生影响。

现在ARM mcu实现提供了与x86相同的结果,但在看到这个后我不确定是否正确。

修改

在这种情况下,精确丢失不是问题,只要它在所有实现中都是相同的

编辑2

我发现这些链接非常有用,评论中已经有一些提示:

2 个答案:

答案 0 :(得分:3)

  

如果我们使用具有double和float算法的算法,我们如何保证在x86和x64 Linux和Windows计算机以及ARM微控制器中在Python和C中运行它的结果相同?

一般来说,除非仔细实施自己的FP操作,否则不能这样做。如果您使用的是各种语言'标准运算符和库以及底层浮点硬件,无法确保不同实现的结果的精确再现性。

首先,浮点数的内部表示存在问题。 C没有指定要使用的表示,即使其他所有都相同,这意味着您不能依赖在不同实现(例如x86_64和ARM)上运行的相同C程序来计算相同的结果。

实际上,现在大多数人都使用IEEE 754浮点格式,而CPython使用底层C实现的double类型来支持其浮点数。然而,即便如此,IEEE也允许在符合要求的实现之间进行一定量的变化。即使是要求严格遵守IEEE规范的指令和编译选项也无法完全解决这个问题。

此外,您指定要同时处理C和Python中的doublefloat,但Python并不具有float的本机模拟。其原生浮点格式(可能)对应于C double。对不同浮点数据类型执行的操作必然会产生不同的结果,即使操作数在数值上等效,并且差异可以在类型转换中持续存在,例如将double结果转换为float

在(机器)代码生成级别还需要考虑其他细节,例如是否或何时将中间结果从FPU寄存器复制到主存储器(可能涉及舍入)以及操作的顺序执行。

  

我们使用的算法使用:

double + double
double + float
double exp(double)
float * float

如果要最小化计算值的差异,那么首先选择一个浮点数据类型,然后在任何地方使用它。为了实现Python和C实现之间的一致性,应该是double

您还应该考虑禁用可能会更改FP操作评估顺序的任何和所有优化。无论如何,这可能都是优化。如果您的C编译器中有可用的选项来强制执行严格的IEEE一致性,那么请打开它们。

您还应该测试所有相关平台上exp()函数的等效性。您可能需要提供自己的实现。

无论你做什么,你应该认识到,如果你的各种实现产生不同的结果,尽管在某种算法意义上都是正确的,那么这本身就是一个结果。它告诉你一些关于计算的真实精度的信息。

你绝不能忘记大多数计算机FP操作产生近似结果,所以即使你设法让所有实现产生相同的结果,这并不意味着这些结果在绝对意义上必然更正确比其他附近的FP值。如果需要数值一致性,那么你应该根据结果的特定精度来量化,以一种能够提供精度的方式实现算法,并忽略精度高于所选精度的差异。

答案 1 :(得分:0)

很难。双精度和浮点数在C或C ++标准中没有形式化,其准确性取决于编译器/ cpu实现。例如,float和double都允许相同。

来自C ++ 17草案(与其他论文类似) basic.fundamental

  

有三种浮点类型:float,double和long double。 double类型提供至少与float一样多的精度,long double类型提供至少与double一样多的精度。 float类型的值集是double类型的值集的子集; double类型的值集是long double类型的值集的子集。浮点类型的值表示是实现定义的。 [注意:本文档对浮点运算的准确性没有要求;另见[support.limits]。 - 结束说明]

我认为C或C ++标准中没有提到IEEE 754

Python派生这个,在C实现上引用浮动类型,其中形式化为also up to implementaion

  

有三种不同的数字类型:整数,浮点数和复数。此外,布尔值是整数的子类型。整数具有无限的精度。浮点数通常在C中使用double实现;