程序问题以近似正弦和余弦值

时间:2014-03-31 22:40:58

标签: python math

我试图编写一个以度为单位的程序,并根据用户选择的一些给定术语来近似sin和cos值。如果您不知道 how找到罪和cos。所以,话虽如此,这是我目前的代码:

import math
def main():
    print()
    print("Program to approximate sin and cos.")
    print("You will be asked to enter an angle and \na number of terms.")
    print("Written by ME")
    print()

    sinx = 0
    cosx = 0

    x = int(input("Enter an angle (in degrees): "))
    terms = int(input("Enter the number of terms to use: "))
    print()

    for i in range(1, terms+1):
        sinx = sinx + getSin(i, x)
        cosx = cosx + getCos(i, x)

    print(cosx, sinx)

def getSin(i, x):
    if i == 1:
        return x
    else:
        num, denom = calcSinFact(i, x)
        sin = num/denom
        return sin

def getCos(i, x):
    if i == 1:
        return 1
    else:
        num, denom = calcCosFact(i, x)
        cos = num/denom
        return cos

def calcSinFact(i, x):
    if i % 2 == 1:
        sign = -1
    if i % 2 == 0:
        sign = +1
    denom = math.factorial(i*2-1)
    num = sign * (x**(i*2-1))
    return num, denom

def calcCosFact(i, x):
    if i % 2 == 1:
        sign = -1
    if i % 2 == 0:
        sign = +1
    denom = math.factorial(i*2)
    num = sign * (x**(i*2))
    return num, denom

它运行但如果我使用上图中显示的示例,我得到cos = -162527117141.85715和sin = -881660636823.117。显然有些事情已经消失。在上图中,答案应为cos = 0.50000000433433和sin = 0.866025445100。我假设它是我在第一个循环中将值加在一起的方式,但我可能是错的。任何帮助表示赞赏!

4 个答案:

答案 0 :(得分:2)

Russell Borogove's comments中指出了几个问题。

问题1是你正在使用的公式

enter image description here

(请参阅wikipedia)期望 x 处于弧度而非度数。绕圆圈旋转360度或2 * pi,因此您可以通过乘以pi / 180将度数转换为弧度,如下所示在python代码中错误地然后正确地获得90度的罪恶。

>>> math.sin(90)
0.8939966636005579
>>> math.sin(90*math.pi/180)
1.0

问题2是代码的其余部分。正如评论中指出的那样,存在一些错误,找到它们的最佳方法是使用一些战略性print语句。但是,您可以用更少的代码行编写程序,而更简单的程序往往具有更少的错误,并且如果它们确实存在问题则更容易调试。

由于这是一项任务,我不会为你做,但一个相关的例子是sinh(x)的系列。

enter image description here

(再次来自维基百科)

您可以使用Python list comprehension以“一次性”生成术语。该列表可以printsum med来获取结果,如下面的程序所示

x = 90 * math.pi / 180 # 90 degrees
n = 5
terms = [x**(2*i+1)/math.factorial(2*i+1) for i in range(n)]
print terms
sinh = sum(terms)
print sinh, math.sinh(x)

该程序的输出是

[1.5707963267948966, 0.6459640975062462, 0.07969262624616703, 0.004681754135318687, 0.00016044118478735975]
2.30129524587 2.30129890231

我直接从求和的数学公式中生成了Python列表理解码,这在左侧的“Sigma”符号中很方便。你可以用类似的方式产生罪和cos。你需要的一个缺失的成分是系列中每个点的标志。数学公式告诉你需要(-1) n 。 Python等价物是(-1)**n,可以插入列表推导代码中的适当位置。

答案 1 :(得分:0)

首先,几点说明。最好在上一次打印结束时或在下一行的开头打印\n,然后清空print()。 使用调试工具,使用logging模块或只使用print并通过比较预期值和返回值来查找错误是有用的。

这是一个适合我的代码:

import math

def main():
    print()
    print("Program to approximate sin and cos.")
    print("You will be asked to enter an angle and \na number of terms.")
    print("Written by ME")
    print()

    sinx = 0
    cosx = 0

    x = int(input("Enter an angle (in degrees): "))
    terms = int(input("Enter the number of terms to use: "))
    print()

    x = x / 180.0 * math.pi; # added

    for i in range(1, terms+1):
        sinx = sinx + getSin(i, x)
        cosx = cosx + getCos(i, x)

    print("Cos:{0}, Sinus:{1}".format(cosx,sinx)); # changed

def getSin(i, x):
    if i == 1:
        return x
    else:
        num, denom = calcSinFact(i, x)
        sin = float(num)/denom # changed
        return sin

def getCos(i, x):
    if i == 1:
        return 1
    else:
        num, denom = calcCosFact(i, x)
        cos = float(num)/denom # changed
        return cos

def calcSinFact(i, x):
    if i % 2 == 1:
        sign = +1 # changed
    if i % 2 == 0:
        sign = -1 # changed
    denom = math.factorial(i*2-1)
    num = sign * (x**(i*2-1))
    return num, denom

def calcCosFact(i, x):
    if i % 2 == 1:
        sign = +1 # changed
    if i % 2 == 0:
        sign = -1 # changed
    denom = math.factorial(i*2-2) # changed
    num = sign * (x**(i*2-2)) # changed
    return num, denom

我改变了什么? (我希望我不会忘记任何事情)

  1. 您的sign个变量错了。恰好相反。所以我在条件下改变了信号。
  2. 这可能没有必要,但是当你将num除以denom时,我添加了从int到float的转换。
  3. 根据definition of the approximation,输入x以弧度为单位。所以我添加了从度数到弧度的转换。 x = x / 180.0 * math.pi;
  4. calcCosFact中的索引错误。它总是高2(即4而不是2,8而不是6 ......)
  5. 我得到了这个结果:     输入角度(以度为单位):180输入要使用的术语数:5     Cos:-0.976022212624,Sinus:0.00692527070751

    现在应该是正确的。当你需要快速做一些数学运算时,我也可以推荐WolphramAlpha

答案 2 :(得分:0)

以下是改进版本:

from math import radians
import sys

# version compatibility shim
if sys.hexversion < 0x3000000:
    # Python 2.x
    inp = raw_input
    rng = xrange
else:
    # Python 3.x
    inp = input
    rng = range

def type_getter(type):
    def fn(prompt):
        while True:
            try:
                return type(inp(prompt))
            except ValueError:
                pass
    return fn
get_float = type_getter(float)
get_int   = type_getter(int)

def calc_sin(theta, terms):
    # term 0
    num    = theta
    denom  = 1
    approx = num / denom
    # following terms
    for n in rng(1, terms):
        num *= -theta * theta
        denom *= (2*n) * (2*n + 1)
        # running sum
        approx += num / denom
    return approx

def calc_cos(theta, terms):
    # term 0
    num    = 1.
    denom  = 1
    approx = num / denom
    # following terms
    for n in rng(1, terms):
        num *= -theta * theta
        denom *= (2*n - 1) * (2*n)
        # running sum
        approx += num / denom
    return approx

def main():
    print(
        "\nProgram to approximate sin and cos."
        "\nYou will be asked to enter an angle and"
        "\na number of terms."
    )

    theta = get_float("Enter an angle (in degrees): ")
    terms = get_int  ("Number of terms to use: ")

    print("sin({}) = {}".format(theta, calc_sin(radians(theta), terms)))
    print("cos({}) = {}".format(theta, calc_cos(radians(theta), terms)))

if __name__=="__main__":
    main()

请注意,因为Maclaurin系列以x = 0为中心,θ更接近0的值将更快收敛:calc_sin(radians(-90), 5)为-1.00000354258但calc_sin(radians(270), 5)为-0.444365928238(距离约157,000倍)正确的值-1.0)。

答案 3 :(得分:0)

通过使用和组合阶乘和整数幂的递归定义,可以完全避免所有幂和因子计算。通过一次计算cos和sin值来获得进一步的优化,这样功率只计算一次。

PI = 3.1415926535897932384;

RadInDeg=PI/180;

def getCosSin(x, n):
    mxx = -x*x; 
    term = 1;
    k = 2;
    cossum = 1;
    sinsum = 1;
    for i in range(n):
        term *= mxx
        term /= k; k+=1
        cossum += term
        term /= k; k+=1
        sinsum += term
    return cossum, x*sinsum

def main():
    print "\nProgram to approximate sin and cos."
    print "You will be asked to enter an angle and \na number of terms."


    x = int(input("Enter an angle (in degrees): "))
    terms = int(input("Enter the number of terms to use: "))
    print 

    x = x*RadInDeg;

    cosx, sinx = getCosSin(x,terms) 

    print cosx, sinx

if __name__=="__main__":
    main()