float128 和 double-double 算术

Posted

技术标签:

【中文标题】float128 和 double-double 算术【英文标题】:float128 and double-double arithmetic 【发布时间】:2015-07-27 07:38:01 【问题描述】:

我在***中看到,以某种方式实现四精度是使用双双运算,即使它的位精度不完全相同:https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format

在这种情况下,我们使用两个双精度来存储值。所以我们做了两个运算来计算结果,每个结果的两倍。

在这种情况下,我们可以在每个双精度数上出现舍入错误,或者它们是避免这种情况的机制?

【问题讨论】:

恐怕你的问题既不清楚又过于宽泛。下载lipforge.ens-lyon.fr/frs/download.php/162/… 并阅读crlibm_private.hAdd22Mul22 的定义,这将使您了解这些事情是如何工作的。 【参考方案1】:

“在这种情况下,我们使用两个 double 来存储值。所以我们每次需要做两次操作。”

这不是双双运算的工作方式。您应该期望在 6 到 20 个 double 操作中实现一个 double-double 操作,具体取决于正在实现的实际操作、融合乘加操作的可用性、一个操作数大于另一个操作数的假设……

例如,当 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 精确地划分为两半,这样每一侧的一半可以与另一侧的一半相乘,得到的结果与 double 完全相同。计算u1*v1u1*v2,……就是这样做的。

mhml 中获得的值可以重叠,因此最后 3 次操作用于将结果重新归一化为两个浮点数之和。

在这种情况下,我们可以在每个双精度数上出现舍入错误,或者它们是避免这种情况的机制?

正如评论所说:

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

您可以在Handbook of Floating-Point Arithmetic 中找到有关用于实现这些结果的所有机制。

【讨论】:

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

以上是关于float128 和 double-double 算术的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .NET 中将 Vector128<float> 转换为 Vector128<int>?

为啥numpy的float128只有63位尾数? [复制]

你可以从两个 np.float 一维数组创建一个 np.complex128 一维数组而不复制吗?

使用 SSE 错误 __m128 到 *float 转换的矩阵乘法?

numpy.float128 在 windows 中不存在,但从 OpenGL 调用

20145123刘森明《Java程序设计》第三周学习总结