﻿ algorithm – 计算正确舍入/几乎正确舍入的浮点立方根 - 代码日志

#### algorithm – 计算正确舍入/几乎正确舍入的浮点立方根

``````  y = pow(x, 1. / 3.);
``````

article描述了如何计算浮点立方根,但推荐的Newton-Raphson算法的最后一次迭代必须以更高的精度进行算法计算正确舍入的双精度立方根.这可能是计算它的最佳方法,但我仍然在寻找一种利用现有正确舍入标准化功能的捷径.

C99包含一个cbrt()函数,但不能指望所有编译器都正确舍入or even faithful. CRlibm的设计者可以选择在提供的函数列表中包含cbrt(),但他们没有.欢迎参考其他正确舍入的数学函数库中可用的实现.

Peter Markstein,“IA-64和基本功能：速度和精度”(Prentice-Hall 2000)

H. Peng,“提取平方根和立方根的算法”,Proceedings 5​​th IEEE International Symposium on Computer Arithmetic,pp.121-126,1981.

new_guess：= old_guess更正

x：= x – x *(x3 – a)/(2 * x3 y)

``````double my_cbrt (double a)
{
double b, u, v, r;
float bb, uu, vv;
int e, f, s;

if ((a == 0.0) || isinf(a) || isnan(a)) {
/* handle special cases */
r = a + a;
} else {
/* strip off sign-bit */
b = fabs (a);
b = frexp (b, &e);
s = e - 3*342;
f = s / 3;
s = s - 3 * f;
f = f + 342;
/* map argument into the primary approximation interval [0.125,1) */
b = ldexp (b, s);
bb = (float)b;
/* approximate cube root in [0.125,1) with relative error 5.22e-3 */
uu =                0x1.2f32c0p-1f;
uu = fmaf (uu, bb, -0x1.62cc2ap+0f);
uu = fmaf (uu, bb,  0x1.7546e0p+0f);
uu = fmaf (uu, bb,  0x1.5d0590p-2f);
/* refine cube root using two Halley iterations w/ cubic convergence */
vv = uu * uu;
uu = fmaf (fmaf (vv, uu, -bb) / fmaf (vv, 2.0f*uu, bb), -uu, uu);
u = (double)uu;
v = u * u; // this product is exact
r = fma (fma (v, u, -b) / fma (v, 2.0*u, b), -u, u);
/* map back from primary approximation interval by jamming exponent */
r = ldexp (r, f);
/* restore sign bit */
r = copysign (r, a);
}
return r;
}
``````