1

我试图创建一个程序来根据“数学函数计算手册”中描述的基于泰勒级数的算法计算以 10 为底的对数(我通过我的大学图书馆找到了在线副本)。

StackOverflow 上的另一个问题给出了类似的算法,我现在找不到链接。

10.3.2 计算以十进制为底的对数

对于十进制基数,以 10 为底的对数是自然选择,将参数分解为指数和分数给我们一个十进制表示:x = (−1)^s × f × 10^n,或者 f = 0,或者 f 在 [1/10, 1) 中。

如果 f ≤√1/10,设 f = 10 × f 和 n = n - 1,使得 f 现在在区间 (√1/10,√10] 内。然后引入变量的变化,泰勒级数展开,以及该展开的多项式表示:

z = (f - 1)/( f + 1),

f = (1 + z)/(1 - z),

D = 2 log10(e)

= 2/ 对数 (10)

log10( f) = D × (z + z3/3 + z5/5 + z7/7 + z9/9 + z11/11 + · · · )

≈ D × z + z3Q(z2),多项式拟合将 D 包含在 Q(z2) 中。

对于 f in (√1/10,√10],我们的 z 大约在 [−0.5195,+0.5195] 范围内。与二进制情况相比,z 的范围更广需要更长的多项式,并且还使得校正项 z3Q(z2)相对较大。它的大小不超过 |0.35z|,因此它只提供一个额外的十进制数字,而不是两个。z 的准确计算比二进制情况更容易:只需设置 z = fl(fl(f− 12)-12)/fl(f+1)。

为此,我用 Python 编写了这个程序:

def log10(x):

n = 0.0 #Start exponent of base 10

while (x >= 1.0):
    x = x/10.0
    n+=1


# if x <= sqrt(1/10)
if(x<=0.316227766016838):
    x = x*10.0
    n = n-1

#Produce a change of variable
z = (x-1.0)/(x+1.0)
D = 4.60517018598809 #2*log10(e)

sum = z
for k in range(3,111,2):
    sum+=(z**k)/k

return D*n*sum

我将结果与math.log10函数进行了比较,结果并不像预期的那样。调试时我最大的问题是理解算法及其工作原理。

4

1 回答 1

1

这是我在建议更正后的源代码(将 return 语句更改为D*sum+n固定的值D,并更改if(x<=0.316227766016838)while(x<=0.316227766016838)。我添加了一些if语句来处理异常情况。

下面的代码在我的 6 位目标精度内运行良好(我用非常小的输入、大的输入对其进行了测试)。

def log10(x):

    # Handle exceptional cases
    if (x == 1):
        return 0
    if (x == 0):
        return float('-Inf')
    if (x < 0):
        return float('nan')

    n = 0 #Start exponent of base 10

    while (x >= 1.0):
        x = x/10.0
        n+=1

    # if x <= sqrt(1/10)
    while(x<=0.316227766016838):
        x = x*10.0
        n = n-1

    #Produce a change of variable
    z = (x-1.0)/(x+1.0)
    D = 0.868588964 #2*log10(e)

    #Taylor series
    sum = z
    for k in range(3,23,2):
        sum+=(z**k)/k

    return D*sum+n
于 2018-03-19T00:23:44.697 回答