【发布时间】:2020-02-26 17:39:08
【问题描述】:
我遵循this paper by Andrew Thall 提供的算法,描述了使用 df64 数据类型执行数学运算的算法,这是一对 32 位浮点数,用于模拟 64 位浮点数的精度。但是,他们在编写除法和平方根函数的方式上似乎存在一些不一致(错误?)。
Division函数在论文中是这样写的:
float2 df64_div(float2 B, float2 A) {
float xn = 1.0f / A.x;
float yn = B.x * xn;
float diff = (df64_diff(B, df64_mult(A, yn))).x;
float2 prod = twoProd(xn, diffTerm);
return df64_add(yn, prodTerm);
}
用于编写此代码的语言似乎是 Cg,以供参考,但如果您将 float2 视为只是 struct float2{float x, y;}; 的别名,您应该能够在 C++ 中解释此代码一些额外的语法来支持直接在类型上的算术运算。
作为参考,这些是此代码中使用的函数的标头:
float2 df64_add(float2 a, float2 b);
float2 df64_mult(float2 a, float2 b);
float2 df64_diff(/*Not provided...*/);
float2 twoProd(float a, float b);
因此有几个问题立即突出:
-
diffTerm和prodTerm从未定义。定义了两个变量,diff和prod, 定义了这些变量,但不确定这些是否是此代码中的预期术语。 - 没有提供
df64_diff的声明。大概这是为了支持减法;但同样,这并不清楚。 -
df64_mult是一个不接受 32 位浮点数作为参数的函数;它只支持两对 32 位浮点数作为参数。目前尚不清楚论文期望这个函数调用如何编译 -
df64_add也一样,它也只接受成对的 32 位浮点数作为参数,但在这里调用的第一个参数只有一个 32 位浮点数。
我有根据地猜测这是此代码的正确实现,但因为即使此函数的正确实现在计算中也存在不可避免的错误,我无法判断它是否正确,即使它给出了值“看起来”是正确的:
float2 df64_div(float2 B, float2 A) {
float xn = 1.0f / A.x;
float yn = B.x * xn;
float diff = (df64_diff(B, df64_mult(A, float2(yn, 0)))).x;
float2 prod = twoProd(xn, diff);
return df64_add(float2(yn, 0), prod);
}
float2 df64_diff(float2 a, float2 b) {
return df64_add(a, float2(-b.x, -b.y));
}
所以我的问题是:论文中看到的该算法的书面实现是否准确(因为它取决于我不知道的 Cg 语言的行为?),或者不是吗?无论如何,我对该代码的插值是否是论文中描述的除法算法的正确实现?
注意:我的目标语言是 C++,因此虽然语言之间的差异(对于这种算法)很小,但我的代码是用 C++ 编写的,我正在寻找 C++ 语言的正确性。
【问题讨论】:
-
看起来很合理。你的测试告诉你什么?我假设你有一个 64 位双精度来测试?遗憾的是,当然,2 x 32 位浮点数只给你 48 位精度,而 64 位双精度为 53 位:-(
-
@ChrisHall 我的测试表明,一些基本的除法工作正常,但就像我说的:由于计算的内在性质,计算涉及一定程度的错误(请参阅您的观察,这种类型的精度高于实际的 IEEE754 64 位浮点数)。所以我需要一个更严格的证据来证明我的实现是正确的(或者至少忠实地再现了论文中描述的算法),而不是仅仅观察一些测试用例落在预期值的合理错误范围内。
-
“Hackers's Delight”(Henry S Warren Jr.)涵盖了整数的多字除法,您所拥有的与此一致。但是,整数版本产生完全正确结果的证据让我很头疼……而且我不知道如何将其扩展到这种情况。对不起。我会测试大量随机生成的尾数,并检查结果是否与舍入到 48 位时的 64 位双除法相同。我会尝试使用相同的 MS 一半的论点,但不同的 LS 一半的划分。检查正确的指数和符号需要更少的测试用例。
-
@ChrisHall 如果有人可以调查一下,这可能是一个很好的答案来提供这个问题以支持所写的算法。多字除法算法可能具有与此算法相同的大部分属性。
-
@ChrisHall 双浮点格式提供 49 位精度。尾部的符号位提供“附加”位。作为推论,当
float映射到 IEEE-754binary32(模数限制幅度显然是由于更有限的指数范围和次法线影响双浮子尾部的潜力)。
标签: c++ algorithm floating-point cg