Использование Python для создания калькулятора Unit Circle? - PullRequest
1 голос
/ 02 января 2012

Будучи младшим программистом, я всегда пытаюсь найти применение своим навыкам.

В любом случае, в настоящее время я беру триггер и работаю над юнит-кругами, формулой для преобразования из степеней.с координатой (sinθ, cosθ) (насколько мне известно).

Однако сложность, с которой я сталкиваюсь, заключается в том, что мне нужно сохранить значения в виде дробей.

В основномалгоритм, который я запланировал:

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

Теперь calc может быть дано любое имя, и он будет функцией, которая возвращает координату (вероятно, в виде кортежа) x и y, заданную x = sinθ и y = cos θ.

Проблема, с которой я столкнулся, заключается в том, что sin в Python возвращает плавающую точку между -1 и 1, однако мне нужно найти способ, чтобы он возвращал дробь.Например, в на этой картинке координаты являются рациональными числами.

Что мне делать?Должен ли я написать свои собственные функции синуса и косинуса, и если да, то как мне это сделать?

Ответы [ 5 ]

5 голосов
/ 02 января 2012

Похоже, вам нужен сторонний модуль, такой как 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)
4 голосов
/ 02 января 2012

Вы пробовали модуль фракция ? Я сам никогда не использовал это, но изумлённый взгляд на этот вопрос.

0 голосов
/ 02 января 2012

Следующий пример определения cos 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    ∞
0 голосов
/ 02 января 2012

Как сказал Игнасио в комментарии, для большинства углов вы не можете представить синус и косинус как дробь, потому что они иррациональные числа.Так что написание собственных функций синуса и косинуса не поможет.(Вы можете попробовать это; это было бы интересное упражнение, но оно было бы довольно медленным. Реализации синуса и косинуса, которые встроены в Python, написаны на C, на основе кода, которому, вероятно, 40 лет, и поколений компьютеров.ученые оптимизировали их, так что вы, вероятно, не сможете добиться большего.)

На самом деле, даже для углов, которые являются круглым числом градусов, вы, как правило, не можете представить синуси косинус как дроби, но во многих случаях вы можете представить их квадратов как дроби.Поэтому я бы посоветовал рассчитать синусоид и косинус.(В качестве примера рассмотрим 45 градусов)

Конечно, даже при использовании хорошего круглого угла вы не получите дробь из (квадратичных) функций синуса и косинуса, потому что они возвращают плавающую точкуномера.Лучше всего конвертировать (приблизительные) десятичные числа в дроби.Вы можете использовать модуль fraction, как предложено от mangobug , чтобы сделать это;если вы это сделаете, воспользуйтесь функцией limit_denominator, потому что вы знаете, что искомые дроби имеют небольшие знаменатели.Кроме того, вы можете написать алгоритм самостоятельно;это еще одно поучительное упражнение.

Наконец, один совет: фактически, координата x соответствует косинусу, а координата y - синусу, если предположить, что ваши углы определены обычным образом.

0 голосов
/ 02 января 2012

Лучший способ, которым я мог придумать, - это взять десятичное число и превратить его в дробь, как в шестом классе. Например .5 -> 1 / .5 = 2 -> 1/2

...