我正在编写一些方法的实现,以便在C中使用GMP查找数字的自然日志.我有两个函数,两个函数都有效,但其中一个运行速度比另一个慢很多.问题是,我认为它是速度最慢的那个.
下面是两个相关的函数,而int main的完整文件可以找到here,而所需的ln_2.txt文件是here.
void taylor_log(mpf_t R,
const mpf_t N,
const mpf_t T)
{
mpf_t x, y, r, pr, tmp, d;
int n = 1;
mpf_init(x);
mpf_init(y);
mpf_init(tmp);
mpf_init(d);
mpf_sub_ui(x, N, 1);
mpf_init_set(y, x);
mpf_init_set(r, x);
mpf_init_set_ui(pr, 0);
mpf_sub(d, r, pr);
mpf_abs(d, d);
while(mpf_cmp(d, T) > 0)
{
mpf_set(pr, r);
mpf_mul(y, y, x);
mpf_div_ui(tmp, y, ++n);
mpf_sub(r, r, tmp);
mpf_mul(y, y, x);
mpf_div_ui(tmp, y, ++n);
mpf_add(r, r, tmp);
mpf_sub(d, r, pr);
mpf_abs(d,d);
}
printf("%d\n", n);
mpf_set(R, r);
}
void hyperbolic_log(mpf_t R,
const mpf_t N,
const mpf_t T)
{
mpf_t x, x2, r, pr, tmp, d;
int n = 1;
mpf_init(x);
mpf_init(x2);
mpf_init(tmp);
mpf_init(d);
mpf_sub_ui(x, N, 1);
mpf_add_ui(tmp, N, 1);
mpf_div(x, x, tmp);
mpf_init_set(r, x);
mpf_init_set_ui(pr, 0);
mpf_mul(x2, x, x);
mpf_sub(d, r, pr);
mpf_abs(d,d);
while(mpf_cmp(d, T) > 0)
{
mpf_set(pr, r);
++n;
mpf_mul(x, x, x2);
mpf_div_ui(tmp, x, ++n);
mpf_add(r, r, tmp);
mpf_sub(d, r, pr);
mpf_abs(d,d);
}
printf("%d\n", n);
mpf_mul_ui(R, r, 2);
}
从理论上讲,第二个函数至少应该运行得更快,因为每个循环的指令更少,并且由于更快的收敛,通常执行更少的循环.这不是我在实践中看到的,因为当我在计算中使用至少33296位计算ln(2)到10000个小数位时,两者都给出了正确的结果,但第一种方法在大约0.150秒内完成,而第二种方法在第二种方法中完成1秒.
我不知道是什么导致一个函数运行速度比另一个慢得多,任何帮助将不胜感激.
编辑:
为清楚起见,我忘了提及在传递给函数之前,将值归一化到范围[0.5,1].对于我已经确认在程序中有效的两个函数,这是相同的,所以从技术上讲,我的问题是当算法提供0.5时.
最佳答案 使用添加的计时功能运行程序,从mpf_mul操作中,对于N = 2,性能命中.
在泰勒案中,
mpf_mul(y, y, x);
xf是-0.5来自mpf_get_d_2exp((long *)& e,N)) – 1,它在gmp结构中的大小为1,无论请求的精度如何.
在双曲线情况下,
mpf_mul(x, x, x2);
x2是0.111 …来自
T = mpf_get_d_2exp((long *)&e, N))
x = (T - 1)/(T + 1)
x2 = x * x
在gmp结构中具有所请求精度的大小.在这种情况下的乘法要贵得多.
编辑
实际上,罪魁祸首是mpf_div(x,x,tmp),它迫使gmp使用整个精度.从x计算的x2具有相同的精度,因此mpf_mul较慢.