1

作为一名年轻的程序员,我一直在努力寻找我的技能的应用。

无论如何,我目前正在学习三角,我们正在研究单位圆,从度数转换为坐标的公式是 (sinθ, cosθ)(据我所知)。

但是,我遇到的困难是我需要将值保留为分数。

基本上,我计划的算法是:

i = 0
while i < 360:
    print(i, "=", calc(i))
    i += 15

现在,可以给 calc 赋予任何名称,并且将是一个函数,它返回 x 和 y 的坐标(可能作为元组),给定 x = sin θ 和 y = cos θ。

我遇到的问题是 Python 中的 sin 返回一个介于 -1 和 1 之间的浮点数,但是,我需要找到一种方法让它返回一个分数。例如,在这张图片 中,坐标是有理数。

我该怎么办?我应该编写自己的正弦和余弦函数吗?如果是,我应该怎么做?

4

5 回答 5

5

看起来您需要一个第三方模块,例如sympy

>>> import sympy
>>> for i in range(0, 360, 15):
...     print i, sympy.sin(sympy.Rational(i, 180) * sympy.pi)
...

0 0
15 sin(pi/12)
30 1/2
45 2**(1/2)/2
60 3**(1/2)/2
75 sin(5*pi/12)
90 1
105 sin(5*pi/12)
120 3**(1/2)/2
135 2**(1/2)/2
150 1/2
165 sin(pi/12)
180 0
195 -sin(pi/12)
210 -1/2
225 -2**(1/2)/2
240 -3**(1/2)/2
255 -sin(5*pi/12)
270 -1
285 -sin(5*pi/12)
300 -3**(1/2)/2
315 -2**(1/2)/2
330 -1/2
345 -sin(pi/12)
于 2012-01-02T08:13:21.693 回答
4

你试过分数模块吗?我本人从未使用过它,但在这个问题上使用它。

于 2012-01-02T07:54:32.407 回答
0

我能想到的最好方法是取十进制数并将其转换为分数,就像你在六年级时所做的那样。例如 .5 -> 1/.5 = 2 -> 1/2

于 2012-01-02T07:55:23.080 回答
0

正如 Ignacio 在评论中所说,对于大多数角度,您不能将正弦和余弦表示为分数,因为它们是无理数。因此,编写自己的正弦和余弦函数将无济于事。(你可以尝试一下;这将是一个有趣的练习,但它们会很慢。Python 中内置的正弦和余弦的实现是用 C 编写的,基于可能有 40 年历史的代码,以及几代计算机科学家们已经对它们进行了优化,所以你可能无法做得更好。)

事实上,即使是整数度的角度,您通常也不能将正弦和余弦表示为分数,但在许多情况下,您可以将它们的平方表示为分数。所以我建议计算正弦平方和余弦平方。(以 45 度为例)

当然,即使使用漂亮的圆角,您也不会从(平方)正弦和余弦函数中得到分数,因为它们返回浮点数。最好的办法是将(近似)十进制数转换为分数。您可以使用mangobugfraction建议的模块来执行此操作;如果这样做,请充分利用该函数,因为您知道要查找的分数具有小分母。或者,您可以自己编写算法;这是另一个有启发性的练习。limit_denominator

最后,一个提示:假设您的角度是按照通常的方式定义的,那么实际上 x 坐标对应于余弦,y 坐标对应于正弦。

于 2012-01-02T08:09:20.297 回答
0

以下示例查找 30 度的 cos 将帮助您了解如何做到这一点

>>> angle=30*math.pi/180 #30 degree in randian
>>> cosine = math.cos(angle) #Lets find the cosine of 30 degree
>>> #Square it. Helps to represent a range of irrational numbers to rational numbers
>>> cos2 = cosine ** 2
>>> # Lets drop some precision. Don't forget about float approximation
>>> cos2 = round(cos2,4)
>>> num = fractions.Fraction(cos2).numerator #Just the Numerator of the fraction
>>> den = fractions.Fraction(cos2).denominator #The denominator of the fraction
>>> def PerfSquare(n): #Square root in an Integer
    return int(n**0.5)**2 == n
# If Perfect Square then Find the Square root or else represent as a root

>>> num = str(num**0.5) if PerfSquare(num) else "root{0}".format(num) # If Perfect Square then Find the Square root or else represent as a root
>>> den = str(den**0.5) if PerfSquare(den) else "root{0}".format(den)
>>> cos = "{0}/{1}".format(num,den) #Combine Numerator and Denominator
>>> print cos
root3/2.0

这里是按上述原理的一个函数

>>> HIGHVALUE=1000
>>> def foo(degree,trigfn):
    angle=degree*math.pi/180 #in randian
    trigval = trigfn(angle) #Lets find the trig function
    #Square it. Helps to represent a range of irrational numbers to rational numbers
    trigval2 = trigval ** 2
    # Lets drop some precission. Don't forget about float aproximation
    trigval2 = round(trigval2,5)
    if trigval > HIGHVALUE:
        return u'\u221e'
    num = fractions.Fraction(trigval2).numerator #Just the Numerator of the fraction
    den = fractions.Fraction(trigval2).denominator #The denominator of the fraction
    if (num > HIGHVALUE or den > HIGHVALUE):
        trigval2 = round(1/trigval2,4)
        den = fractions.Fraction(trigval2).numerator #Just the Numerator of the fraction
        num = fractions.Fraction(trigval2).denominator #The denominator of the fraction
    if num > HIGHVALUE or den > HIGHVALUE or num < 1 or den < 1:
        #Cannot be represented properly
        #Just return the value
        return str(round(trigval,4))
    # If Perfect Square then Find the Square root or else represent as a root
    num = str(int(num**0.5)) if PerfSquare(num) else u"\u221a{0}".format(num)
    den = str(int(den**0.5)) if PerfSquare(den) else u"\u221a{0}".format(den)
    return u"{0}".format(num) if den == "1" else u"{0}/{1}".format(num,den) #Combine Numerator and Denominator

运行的结果

>>> def Bar():
    print 'Trig\t'+'\t'.join(str(x) for x in xrange(0,91,15))
    for fn in [math.sin,math.cos,math.tan]:
        print fn.__doc__.splitlines()[0],'\t',
        print '\t'.join(foo(angle,fn) for angle in xrange(0,91,15) )

>>> Bar()
Trig    0       15       30       45       60       75       90
sin(x)  0.0    0.2588    1/2    1/√2    √3/2    0.9659    1
cos(x)  1      0.9659    √3/2    1/√2    1/2    0.2588    0.0
tan(x)  0.0    0.2679    1/√3    1      √3    3.7321    ∞
于 2012-01-02T09:28:23.987 回答