float128 和双双算术

float128 and double-double arithmetic

提问人:Romain Picot 提问时间:7/27/2015 最后编辑:phuclvRomain Picot 更新时间:9/10/2020 访问量:2397

问:

我在维基百科上看到,实现四精度的某种方法是使用双精度算术,即使它在位方面的精度不完全相同:https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format

在本例中,我们使用两个双精度来存储值。因此,我们进行两次操作来计算结果,对应结果的每个双倍。

在这种情况下,我们可以对每个双精度进行舍入误差,或者有一种机制可以避免这种情况?

C++ 浮点 IEEE-754 双算术

评论

1赞 Pascal Cuoq 7/27/2015
恐怕你的问题既不清楚又太宽泛了。下载 lipforge.ens-lyon.fr/frs/download.php/162/...并阅读 和 中的定义,这将使您了解这些东西是如何工作的。Add22Mul22crlibm_private.h

答:

10赞 Pascal Cuoq 7/27/2015 #1

“在这种情况下,我们使用两个双精度来存储值。因此,我们每次需要进行两次操作。

这不是双倍算术的工作方式。您应该期望在 6 到 20 个双精度操作的任何地方实现一个双精度操作,具体取决于正在实现的实际操作、融合乘加操作的可用性、一个操作数大于另一个操作数的假设......

例如,当 FMA 指令不可用时,这里是双倍乘法的一个实现,取自 CRlibm

#define Mul22(zh,zl,xh,xl,yh,yl)                      \
{                                                     \
double mh, ml;                                        \
                              \
  const double c = 134217729.;                \
  double up, u1, u2, vp, v1, v2;              \
                              \
  up = (xh)*c;        vp = (yh)*c;            \
  u1 = ((xh)-up)+up;  v1 = ((yh)-vp)+vp;          \
  u2 = (xh)-u1;       v2 = (yh)-v1;                   \
                              \
  mh = (xh)*(yh);                     \
  ml = (((u1*v1-mh)+(u1*v2))+(u2*v1))+(u2*v2);        \
                              \
  ml += (xh)*(yl) + (xl)*(yh);                \
  *zh = mh+ml;                        \
  *zl = mh - (*zh) + ml;                              \
}

仅前 8 个运算就是将操作数中的每个 double 精确地分成两半,以便可以将每侧的一半乘以另一侧的一半,并且得到的结果正好为 .计算 , , ...正是这样做的。doubleu1*v1u1*v2

中获取的值可以重叠,因此最后 3 次运算用于将结果重新规范化为两个浮点数的总和。mhml

在这种情况下,我们可以对每个双精度进行舍入误差,或者有一种机制可以避免这种情况?

正如评论所说:

/*
 * computes double-double multiplication: zh+zl = (xh+xl) *  (yh+yl)
 * relative error is smaller than 2^-102
 */

您可以在浮点运算手册中找到用于实现这些结果的所有机制。

评论

0赞 Romain Picot 7/27/2015
好的,所以双倍算术是基于补偿算法的。所以你当然需要两个以上的操作。这是我没有发现的。谢谢。如果您使用 FastTwoSum,只需稍作修改,您就会有 3 个运算(以及绝对值和一个分支)而不是 6 个运算(对于这部分:6 到 20 个双倍操作)
1赞 Pascal Cuoq 7/27/2015
@RomainPicot 在我看来,只需要 3 次运算(如果我们假设参数的顺序是已知的,则不计算条件)的是 Add12,它不是双双操作,而是编写它们的方便辅助函数。无论如何,无论实际实施的操作和可用的假设如何,计算操作的数量并不是一个精确的科学:)
0赞 Romain Picot 7/27/2015
你是对的。即使运算较少,在大多数情况下,由于分支的原因,您的速度也会变慢。(我不记得这是否来自《浮点算术手册》或《计算机编程的艺术》)。对我来说最重要的是看到使用了补偿算法:-)