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
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;