使用Python创建单位圆计算器?

发布于 2024-12-24 21:50:00 字数 518 浏览 1 评论 0原文

作为一名年轻的程序员,我总是试图寻找我的技能的应用。

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

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

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

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

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

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

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

As a younger programmer, I'm always trying to look for applications of my skills.

Anyways, I'm currently taking trig and we're working on unit circles, the formula for converting from degrees to a coordinate is (sinθ, cosθ) (to the best of my knowledge).

However, the difficulty I'm having is that I need to keep the values as fractions.

Basically, the algorithm I've planned is:

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

Now, calc can be given any name, and will be a function that returns a coordinate (probably as a tuple) of x and y given x = sin θ and y = cos θ.

The issue I'm having is that sin in Python returns a floating point between -1 and 1, however, I need to find a way to have it return a fraction. For example, in this picture the coordinates are rational numbers.

What should I do? Should I write my own sine and cosine functions, and if so, how should I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

青衫负雪 2024-12-31 21:50:00

您似乎需要一个第三方模块,例如 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)

It looks like you need a third-party module such as 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)
一笔一画续写前缘 2024-12-31 21:50:00

您是否尝试过 fraction 模块?我自己从未使用过它,但对这个问题感到困惑。

Did you try the fraction module? I myself have never used it but goggled it in respect to this question.

东走西顾 2024-12-31 21:50:00

我能想到的最好的方法就是将小数转化为分数,就像六年级时那样。例如0.5-> 1/.5=2-> 1/2

The best way that I could think of is to take the decimal number and turn it into a fraction, just like you would in 6th grade. For instance .5 -> 1/.5 = 2 -> 1/2

很酷又爱笑 2024-12-31 21:50:00

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

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

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

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

As Ignacio said in a comment, for most angles you can't represent the sine and cosine as a fraction, because they're irrational numbers. So writing your own sine and cosine functions won't help. (You could try it; it'd be an interesting exercise, but they would be pretty slow. The implementations of sine and cosine that are built into Python are written in C, based on code that's probably 40 years old, and generations of computer scientists have optimized the heck out of them so you probably can't do any better.)

As a matter of fact, even for angles that are a round number of degrees, you generally can't represent the sine and cosine as fractions, but in many cases you can represent their squares as fractions. So I would suggest calculating the sine squared and cosine squared. (Think about 45 degrees as an example)

Of course, even using a nice round angle, you're not going to get a fraction out of the (squared) sine and cosine functions because they return floating-point numbers. Your best bet is to convert the (approximate) decimal numbers into fractions. You can use the fraction module as suggested by mangobug to do this; if you do, make liberal use of the limit_denominator function because you know that the fractions you're looking for have small denominators. Alternatively, you could write the algorithm yourself; that's another instructive exercise.

Finally, one tip: it's actually the x coordinate that corresponds to the cosine and the y coordinate to the sine, assuming your angles are defined the usual way.

燕归巢 2024-12-31 21:50:00

下面的求 30 度余弦的示例将帮助您了解如何做到这一点

>>> 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    ∞

The following example to find the cos of 30 degree will help you understand how can you possibly do it

>>> 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

Here is a function by the above principle

>>> 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

the result from the run

>>> 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    ∞
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文