计算自然对数的快速算法,之需要依赖sqrt,嵌入式设备上可用

在1982年,Tateaki. Sasaki 和 Yasumasa Kanada 发表了一篇论文:Practically Fast Multiple-Precision Evaluation of LOG(x)。在这篇只有四页的论文中,他们介绍了一个计算自然对数的快速算法。

 

c 代码如下:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define ln10 2.30258509299404568401799145468
#define pi2 6.283185307179586476925286766559
// 1e-14
#define eps2 0.00000000000001
// 1e-28
#define eps1 (eps2 * eps2)

float sqrt_tmp(float x)
{
    if (x < 0) return 0;
    if (x == 0) return 0;
    float y = (float) sqrtf(x);
    return (y + x / y) / 2;
}

float negative_log(float q)
{ // q in ( 0.01, 0.1 ]
    int p = 1;
    float r = q, s = q, n = q, q2 = q * q, q1 = q2 * q;
    for (p = 1; (n *= q1) > eps1; s += n, q1 *= q2)
        r += (p = !p) ? n : -n;
    float u = 1 - 2 * r, v = 1 + 2 * s, t = u / v;
    float a = 1, b = sqrt_tmp(1 - t * t * t * t);
    for (; a - b > eps2; b = sqrt_tmp(a * b), a = t) t = (a + b) / 2;
    return pi2 / (a + b) / v / v;
}

float logf(float x)
{
    if (x <= 0) return 0;
    if (x == 1) return 0;

    int k = 0;
    for (; x > 0.1; k++) x /= 10;
    for (; x <= 0.01; k--) x *= 10;
    return k * ln10 - negative_log(x);
}

int main(int argc, char *argv[])
{
    float input;
    sscanf(argv[1], "%f", &input);
    float r = logf(input);
    printf("%f\n", r);

    return 0;
}

总体也不是很耗时间,总共循环才13个。

 

posted @ 2019-12-30 11:23  微信公众号--共鸣圈  阅读(475)  评论(0编辑  收藏  举报