我正在开发一个执行大量浮点计算的应用程序.我们在Intel x86上使用VC++,具有双精度浮点值.我们声称我们的计算精确到n个十进制数字(现在7,但试图声称15).
当我们的结果略有变化时(由于代码重构,清理等),我们会花费大量精力来验证我们的结果与其他来源.我知道有许多因素影响整体精度,例如FPU控制状态,编译器/优化器,浮点模型以及操作本身的总体顺序(即算法本身),但考虑到固有的不确定性在FP计算中(例如,0.1不能表示),对所有计算声明任何特定程度的精确度似乎无效.
我的问题是:在没有进行任何分析(例如区间分析)的情况下,对FP计算的准确性提出任何要求是否有效?如果是这样,可以提出什么要求以及为什么?
编辑:
因此,假设输入数据精确到n位小数,可以保证任何任意计算的结果,只要使用双精度?例如,如果输入数据有8位有效十进制数字,则输出将至少有5位有效十进制数字......?
我们正在使用数学库,并且不知道他们可能会或可能不会做出任何保证.我们使用的算法不一定以任何方式分析精度.但即使给定一个特定的算法,实现也会影响结果(例如,只改变两个加法运算的顺序).使用双精度时是否有任何固有的保证?
另一个编辑:
我们根据经验验证我们的结果与其他来源.那么,当我们达到10位数的准确度时,我们才会幸运吗?
简答:不.
理由:你证明了(是的证明)你并没有失去任何精确度吗?你确定吗?您是否了解您用于超越函数的任何库函数的内在精度?你有没有计算加性误差的极限?如果您使用的是迭代算法,那么在退出时,您是否知道它已融合的程度如何?这个东西很难.
除非您的代码仅使用IEEE 754(+, - ,*,/和平方根)中指定的基本操作,否则您甚至不知道每次调用控件之外的库函数的精度损失(三角函数,exp/log, ...)介绍.基本5之外的功能不保证是1ULP,并且通常不精确.
你可以进行实证检验,但这就是它们的存在......经验.不要忘记关于软件的EULA没有保修的部分!
如果您的软件是安全关键的,并且没有调用库实现的数学函数,您可以考虑http://www-list.cea.fr/labos/gb/LSL/fluctuat/index.html.但只有关键软件才值得付出努力,并且有机会适应此工具的分析约束.
在您编辑之后,您似乎主要关注您的编译器在后面做事情.这是一种自然的恐惧(因为就像数学函数一样,你无法控制).但这不太可能成为问题.您的编译器可能会以比您要求的更高的精度进行计算(当您要求提供64位双精度数或64位双精度数时,当您要求32位浮点数时).这是C99标准允许的.在舍入到最近,这可能会引入双舍入误差.但是你只是输掉了1ULP,而且不经常你不用担心.这可能会导致令人费解的行为,如:
float x=1.0;
float y=7.0;
float z=x/y;
if (z == x/y)
...
else
... /* the else branch is taken */
Run Code Online (Sandbox Code Playgroud)
但是当你==在浮点数之间使用时,你正在寻找麻烦.
当你有代码有意取消时,例如在Kahan的求和算法中:
d = (a+b)-a-b;
Run Code Online (Sandbox Code Playgroud)
并且编译器优化了它d=0;,你有一个问题.是的,这种优化"好像浮动操作是关联的"已经在一般的编译器中看到了.它是不是由C99不允许的.但我认为情况已经好转了.编译器作者已经越来越意识到浮点的危险,并且不再试图如此积极地进行优化.另外,如果您在代码中执行此操作,则不会问这个问题.
| 归档时间: |
|
| 查看次数: |
452 次 |
| 最近记录: |