1

若いプログラマーとして、私は常に自分のスキルのアプリケーションを探しています。

とにかく、私は現在三角関数を使用しており、単位円に取り組んでいます。度から座標に変換する式は (sinθ、cosθ) (私の知る限り) です。

ただし、私が抱えている問題は、値を分数として保持する必要があることです。

基本的に、私が計画したアルゴリズムは次のとおりです。

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

ここで、calc には任意の名前を付けることができ、x = sin θ および y = cos θ を指定して x と y の座標を (おそらくタプルとして) 返す関数になります。

私が抱えている問題は、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

Ignacio がコメントで述べたように、ほとんどの角度では、サインとコサインは無理数であるため、分数として表すことはできません。したがって、独自の正弦関数と余弦関数を記述しても役に立ちません。(試してみることもできます。興味深い演習になるでしょうが、かなり遅くなるでしょう。Python に組み込まれている正弦と余弦の実装は、おそらく 40 年前のコードと世代のコンピューターに基づいて C で記述されています。科学者はそれらを最適化したので、おそらくこれ以上のことはできません.)

実際のところ、角度が丸められた度数であっても、通常、サインとコサインは分数として表すことはできませんが、多くの場合、それらの2 乗は分数として表すことができます。したがって、サインの二乗とコサインの二乗を計算することをお勧めします。(例として45度程度で考えてください)

もちろん、適切な丸め角度を使用しても、(2 乗) サイン関数とコサイン関数は浮動小数点数を返すため、分数を取得することはできません。あなたの最善の策は、(おおよその) 10 進数を分数に変換することです。これを行うには、 mangobugfractionが提案するモジュールを使用できます。その場合は、探している分数の分母が小さいことがわかっているため、関数を自由に使用してください。または、アルゴリズムを自分で作成することもできます。それは別の有益な演習です。limit_denominator

最後に、1 つのヒント: 実際には、角度が通常の方法で定義されていると仮定すると、コサインに対応する 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 に答える
0

私が思いつく最善の方法は、6 年生のときと同じように、10 進数を分数に変換することです。たとえば、.5 -> 1/.5 = 2 -> 1/2

于 2012-01-02T07:55:23.080 に答える