级数展开的三角函数

2024-04-19 09:51:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试编写模拟math.sinmath.tan的函数,但不是使用math库,而是使用级数展开执行计算。你知道吗

公式来自数学SE,How would you calculate the Tangent without a calculator?

sin(x) = x − x^3/3! + x^5/5! −...

tan(x) = sin(x) / √(1 − sin(x)^2)

这是我的尝试,但我不知道如何执行符号翻转+/-/+/。。。sin系列扩展的一部分:

from math import factorial

res = 0
for i in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]:
    res += 1**i/factorial(i)

print(res)  # 1.1752011936438016

结果不正确,因为我没有应用+/-开关。我可以添加一个if/else子句,但这看起来很混乱。有更好的办法吗?你知道吗

注意:这个问题是@Lana昨天发布的now deleted question的修饰版本。你知道吗


Tags: the函数youres数学mathsinhow
2条回答

你很接近。下面是使用sumenumerate进行系列扩展的一种方法。你知道吗

enumerate的工作原理是获取iterable的每个值并附加一个索引,即0代表第一项,1代表第二项,等等。然后我们只需要测试索引是偶数还是奇数,并使用ternary statement。你知道吗

此外,您可以使用range而不是列出扩展中所需的奇数。你知道吗

from math import factorial

def sin(x, n=20):
    return sum(x**j/factorial(j)*(1 if i%2==0 else -1)
               for i, j in enumerate(range(1, n, 2)))

def tan(x):
    return sin(x) / (1-(sin(x))**2)**0.5

print(tan(1.2))  # 2.572151622126318

您可以避免使用三元语句和enumerate

def sin(x, n=20):
    return sum((-1)**i * x**(2*i+1) / factorial(2*i+1) for i in range(n))

如果你用手写出前几个术语,等价性就会变得很清楚。你知道吗

备注:

  • tan函数的符号只对第一象限和第四象限正确。这与您提供的公式一致。您可以对输入执行简单的转换来说明这一点。你知道吗
  • 可以通过增加参数n来提高精度。你知道吗
  • 你也可以在没有库的情况下计算阶乘,但我把它作为练习。你知道吗

通过使用前一项计算总和的下一项,可以避免在每一步重新计算x**n和阶乘:

def sin2(x, n=20):
    curr =  x
    res = curr 
    for i in range(2, n, 2):
        curr *= - x**2/(i*(i+1))
        res += curr
    return res

与jpp的版本相比,它的速度大约是jpp的两倍:

from math import factorial

def sin(x, n=20):
    return sum(x**j/factorial(j)*(1 if i%2==0 else -1)
               for i, j in enumerate(range(1, n, 2)))


%timeit sin(0.7)
# 100000 loops, best of 3: 8.52 µs per loop
%timeit sin2(0.7)
# 100000 loops, best of 3: 4.54 µs per loop

如果我们一劳永逸地计算- x**2,速度会更快一些:

def sin3(x, n=20):
    curr =  x
    res = 0
    minus_x_squared = - x**2
    for i in range(2, n, 2):
        res += curr
        curr *= minus_x_squared/(i*(i+1))
    return res

%timeit sin2(0.7)
# 100000 loops, best of 3: 4.6 µs per loop

%timeit sin3(0.7)
# 100000 loops, best of 3: 3.54 µs per loop

相关问题 更多 >