Floating point 检索浮点操作中丢失的数字

Floating point 检索浮点操作中丢失的数字,floating-point,Floating Point,是否有可靠的标准方法来检索浮点运算中丢失的尾数 即 是的,有。这是中使用的基本操作,与您的代码非常相似。其工作原理如下: assert(a >= b) sum = a + b bPrime = sum - a resid = b - bPrime a+b(精确值,而不是计算数量)现在正好等于sum+resid(同样,精确值)。当然,您不能直接使用它:在浮点上下文中计算sum+resid只会产生sum。Kahan求和的思想是在添加后续项时重新引入残差。其他方法只是将值保留为一组具有不重叠尾

是否有可靠的标准方法来检索浮点运算中丢失的尾数


是的,有。这是中使用的基本操作,与您的代码非常相似。其工作原理如下:

assert(a >= b)
sum = a + b
bPrime = sum - a
resid = b - bPrime
a+b
(精确值,而不是计算数量)现在正好等于
sum+resid
(同样,精确值)。当然,您不能直接使用它:在浮点上下文中计算
sum+resid
只会产生
sum
。Kahan求和的思想是在添加后续项时重新引入残差。其他方法只是将值保留为一组具有不重叠尾数的浮点数的隐式和。

Fast2Sum 下面解释了一个警告,问题中显示的算法是T.J.Dekker在1971年描述的Fast2Sum算法,尽管它在1965年首次作为William Kahan的“补偿和法”的一部分出现。如果:

  • 浮点基数是2或3
  • 低于正常值的数字可用
  • 每项操作均以四舍五入的方式进行
  • 每个操作都以相同的浮点精度执行,并且
  • sum
    不会溢出到无穷大
然后,根据Jean-Michel Muller等人在《浮点算术手册》2010年第4.3.1条“Fast2Sum算法”中的规定,
sum
lostDigits
的实数和等于
a
b

警告 Fast2Sum要求
a
指数至少与
b
指数一样大。因此,如果
a
b
可能为阴性,则测试
a>b
不充分
fabs(a)>fabs(b)
足以确保then子句有效,但不能保证else子句有效。相反,Muller等人给出了一个2Sum算法,该算法适用于任何基数和任何
a
b
的正常数字,前提是不存在溢出或半径大于2的下溢1:

脚注
1正如aka.nice所指出的,如果支持低于正常值,则下溢似乎不会成为问题。由于加法和减法运算不涉及位置低于其操作数的任何数字,因此与为避免下溢而缩放的相同运算相比,下溢到次正常结果的计算结果不应有任何差异。在这个回答中,我报告了Muller等人所做的陈述。如果支持低于正常值,代码可能会与底流一起工作,但我不愿意在未经仔细考虑的情况下更改Muller等人。

您的目的是什么?通常不会,因为您的操作仍然会失去精度。您可能希望使用高精度数学库(例如,在其中设置位数),但这可能会很慢(但对于检查/理解浮点数或少数特定计算很有用)。仅供参考,浮点数分数部分的首选术语是“有效位”,而不是“尾数”。“尾数”是一个古老的词,表示对数的分数部分。尾数是对数的:在尾数上加上一个数字。有效位是线性的:有效位乘以一个数字。@GiacomoCatenazzi:如果你对巧妙使用浮点运算的目的有疑问,然后请查阅一本教科书,如Muller等人的《浮点运算手册》。熟练的实践者通常以经过适当验证和设计的方式使用这些技术,这与堆栈溢出上流行的许多业余信息形成了对比。如果你的问题是为了劝阻OP不要这样做,那么请停止。这是正确使用浮点运算的正确方法。@EricPostpischil:我想你误解了我的评论。这个问题没有什么背景。现在我看到了答案,我认为你是对的。无论如何,我并没有劝阻。在任何情况下,如果您这样做了,也要做一个测试函数:不幸的是,新编译器或意外的标志设置并不少见,这会导致不必要的优化(C对浮点更严格,但GCC有标志来增加优化/排序操作)。
if(a>b)
如果
a、b
都是正数,那么
if(a>b)
有一定意义。通用的
Sum()
需要处理其他情况。在base 2中,如果操作发生下溢,则操作将是精确的。我只是想知道为什么在其他基地要注意下溢?@aka.nice:我同意。作为脚注添加。
assert(a >= b)
sum = a + b
bPrime = sum - a
resid = b - bPrime
s  = a  + b;
ap = s  - b;
bp = s  - ap;
ad = a  - ap;
bd = b  - bp;
t  = ad + bd;