如何用 C++ 编写一个以 10 为底的日志函数?

How to write a log base 10 function in c++?

我知道这似乎是一个重复的问题,但我在之前的问题中找不到我的答案。 我的意思是如何通过简单的循环而不是使用 C++ 中的内置日志函数来编写一个以 10 为底的日志函数。

假设 "log base 10" 你的意思是 "the number of times n can be divided by 10 before resulting in a value < 10":

log = 0;
// Assume n has initial value N
while ( n >= 10 ) {
    // Invariant: N = n * 10^log
    n /= 10;
    log += 1;
}

最简单的方法是用 Taylor series 计算自然对数 (ln)。找到自然对数后,只需将其除以 ln(10) 即可得到以 10 为底的对数。

泰勒级数在 C 中实现起来非常简单。如果 z 是您要查找对数的数字,您只需循环几次迭代,将累加器乘以 (z-1)每一次。在一定程度上,您 运行 的迭代次数越多,您的结果就越准确。针对 libC log10() 版本检查几次,直到您对精度感到满意为止。

这是一个"numeric approach"。还有其他数字解决方案可以提供更准确的结果来查找数字的对数。其中一些可以在我给你的维基百科 link 中找到。

使用牛顿法可以更快地收敛。使用类似这样的东西(手写未编译或测试使用 f(r) = 2**r - x 来计算 log2(x) ):

double next(double r, double x) {
    static double one_over_ln2 = 1.4426950408889634;
    return r - one_over_ln2 * (1 - x / (1 << static_cast<int>(r)));

double log2(double x) {
    static double epsilon = 0.000000001; // change this to change accuracy
    double r = x / 2;. // better first guesses converge faster
    double r2 = next(r, x);
    double delta = r - r2;
    while (delta * delta > epsilon) { 
        r = r2;
        r2 = next(r, x);
        delta = r - r2
    }
    return r2;
}

double log10(double x) {
    static double log2_10 = log2(10);
    return log2(x) / log2_10;
}