4

我正在开发一个执行大量浮点计算的应用程序。我们在 Intel x86 上使用具有双精度浮点值的 VC++。我们声称我们的计算精确到n 个十进制数字(现在是 7,但试图声称是 15)。

当我们的结果略有变化时(由于代码重构、清理等),我们会付出很多努力来对照其他来源验证我们的结果。我知道影响整体精度的因素很多,例如 FPU 控制状态、编译器/优化器、浮点模型以及操作本身的整体顺序(即算法本身),但考虑到固有的不确定性在 FP 计算中(例如,不能表示 0.1),为所有计算声明任何特定程度的精度似乎是无效的。

我的问题是:在不进行任何类型的分析(例如区间分析)的情况下,对 FP 计算的准确性做出任何声明是否有效?如果是这样,可以提出什么索赔,为什么?

编辑:

因此,假设输入数据精确到小数点后n位,那么在使用双精度的情况下,是否可以对任意计算的结果做出任何保证?例如,如果输入数据有 8 位有效十进制数字,则输出将至少有 5 位有效十进制数字... ?

我们正在使用数学库,并且不知道他们可能会或可能不会做出任何保证。我们使用的算法不一定以任何方式进行精确分析。但是即使给定一个特定的算法,实现也会影响结果(例如,只是改变两个加法运算的顺序)。使用双精度时是否有任何内在保证?

另一个编辑:

我们确实根据其他来源凭经验验证了我们的结果。那么,当我们达到 10 位数的准确度时,我们只是幸运吗?

4

7 回答 7

7

与所有此类问题一样,我只需要简单地回答文章What Every Computer Scientist Should Know About Floating-Point Arithmetic。对于您正在谈论的工作类型,它绝对是必不可少的。

于 2010-02-15T02:17:37.510 回答
6

简短的回答:没有。

原因:您是否证明(是证明)您在进行过程中没有丢失任何精度?你确定吗?您了解用于超越函数的任何库函数的内在精度吗?你计算过附加误差的极限吗?如果您使用的是迭代算法,您知道退出时它的收敛程度吗?这东西很难。

于 2010-02-15T02:18:01.033 回答
5

除非您的代码仅使用 IEEE 754 中指定的基本操作(+、-、*、/ 和平方根),否则您甚至不知道每次调用您无法控制的库函数(三角函数、exp/log、 ...) 介绍。基本 5 之外的函数不能保证,而且通常不会,精确到 1ULP。

您可以进行经验检查,但这就是它们仍然存在的……经验。不要忘记软件的 EULA 中没有保修的部分!

如果您的软件对安全至关重要,并且没有调用库实现的数学函数,您可以考虑http://www-list.cea.fr/labos/gb/LSL/fluctuat/index.html。但只有关键软件才值得付出努力,并且有机会适应该工具的分析约束。

在你的编辑之后,你似乎最关心你的编译器在你背后做事。这是一种自然的恐惧(因为就像数学函数一样,你无法控制)。但这不太可能成为问题。您的编译器的计算精度可能比您要求的更高(当您要求 64 位双精度时,80 位扩展或当您要求 32 位浮点数时,64 位双精度)。这是 C99 标准所允许的。在四舍五入中,这可能会引入双舍入错误。但是您损失的只是 1ULP,而且这种情况很少发生,您不必担心。这可能会导致令人费解的行为,例如:

float x=1.0;
float y=7.0;
float z=x/y;
if (z == x/y) 
...
else
... /* the else branch is taken */

==但是当你在浮点数之间使用时你正在寻找麻烦。

当您有故意取消的代码时,例如在 Kahan 的求和算法中:

d = (a+b)-a-b;

并且编译器将其优化为d=0;,您有问题。是的,这种优化“好像浮动操作是关联的”已经在一般编译器中看到过。C99不允许。但我认为情况已经好转了。编译器作者已经更加意识到浮点的危险,不再尝试如此积极地进行优化。另外,如果你在你的代码中这样做,你就不会问这个问题。

于 2010-02-15T02:20:01.943 回答
2

鉴于您的机器、编译器、运行时库和操作系统的供应商没有对浮点精度做出任何此类声明,您应该将其视为一个警告,即您的团队应该警惕做出可能受到影响的声明如果客户将您告上法庭,将受到严格审查。

如果不对整个系统进行正式验证,我会避免这种说法。我从事对人类安全有间接影响的科学软件的工作,所以我们过去曾考虑过此类事情,我们不会做出此类声明。

您可以对双(长度)浮点计算的精度提出无用的声明,但这基本上毫无价值。

参考:ACM Transactions on Programming Languages and Systems验证浮点计算的陷阱30, 3 (2008) 12

于 2010-02-15T02:35:19.160 回答
1

不,您不能提出任何此类索赔。如果您想这样做,您需要执行以下操作:

  • 聘请数值计算专家来分析您的算法。
  • 要么让你的库和编译器供应商向上述专家开放他们的资源进行分析,要么让他们签署硬语义和错误界限。

双精度浮点通常具有大约 15 位的十进制精度,但是有太多方法会丢失部分或全部精度,对于非专家诊断来说太微妙了,无法做出任何声明喜欢你想要声称的东西。

有一些相对简单的方法可以保持运行错误界限,这可以让您对任何特定计算进行准确性声明,但是对使用您的软件执行的所有计算的准确性进行声明是一个更高的要求。

于 2010-02-15T04:54:14.940 回答
0

英特尔 CPU 上的双精度数略好于 15 位有效数字(十进制)。

简单计算的潜在误差在 n/1.0e15 的范围内,其中 n 是您正在使用的数字的数量级。我怀疑英特尔对基于 CPU 的 FP 计算的准确性有规范。

通常会记录库函数(如 cos 和 log)的潜在错误。如果没有,您可以查看源代码(例如 GNU 源代码)并计算它。

您可以像手动计算一样计算误差线。

一旦你这样做了,你就可以通过对计算进行明智的排序来减少错误。

于 2010-02-15T04:36:18.867 回答
0

由于您似乎担心任意计算的准确性,您可以尝试以下方法:使用不同的舍入模式运行代码以进行浮点计算。如果结果非常接近,你可能没问题。如果结果不接近,您需要开始担心。

结果的最大差异将为您提供计算准确性的下限。

于 2010-02-15T05:41:26.503 回答