2016-06-23 18 views
0

フラグの領域Building Skills with Pythonを解決しようとしています。私は青い領域のために解決しようとしていますが、私は約2%オフです。さらに、他の領域を合計すると、合計はフラグ自体の面積と等しくなりません。次のように私のコードは次のとおりです。Python - フラグの領域

import math 


def area_star(width): 
    a = 36.00 
    b = 72.00 

    radius_star = 0.0308 * width 

    a_radians = float(a) * float(math.pi)/float(180) 
    b_radians = float(b) * float(math.pi)/float(180) 

    a_sin = math.sin(float(a_radians)/float(2)) 
    b_sin = math.sin(float(b_radians)/float(2)) 

    top = a_sin*b_sin 

    c_radians = float((a+b)*math.pi)/float(180) 
    c_sin = math.sin(c_radians) 

    bottom = 0.5 * c_sin  
    return 5 * float(top)/float(bottom) * radius_star * radius_star 
def fifty_stars(width): 
    return 50 * area_star(width) 
def calculate_areas(width): 
    WIDTH = width 
    length = 1.9 * WIDTH 
    width_union = float(7)/float(13) * WIDTH 
    length_union = 0.76*WIDTH 
    NUMBER_RED_STRIPES = 7 
    NUMBER_WHITE_STRIPES = 6 

    width_strip_denom = NUMBER_RED_STRIPES+NUMBER_WHITE_STRIPES 
    width_strip = float(1)/float(width_strip_denom)*WIDTH 

    blue_area = length_union * width_union - fifty_stars(WIDTH) 
    white_area = 3 * width_strip * (length*length_union)+3*width_strip*length+fifty_stars(WIDTH) 
    red_area = 4 * width_strip*(length*length_union)+3*width_strip*length 




    print 'Our width was given as : %f' %WIDTH 
    print 'Our length calculates as : %f' %length 

    print 'Width of our union is: %f' %width_union 
    print 'Length of our union is: %f' %length_union 

    print 'Area of a star is %f'%area_star(WIDTH) 
    print 'Area of 50 stars is %f'%fifty_stars(WIDTH) 

    print 'Area of our flag in total is : %f '%(WIDTH*length) 
    print 'Actual WHITE AREA is %f'%white_area 
    print 'Actual RED AREA is %f'%red_area 
    print 'Expected BLUE AREA is %f' %(WIDTH*length*.1873) 
    print 'Actual BLUE AREA is %f'%blue_area 

    print 'SumofallAreas: %f' % (red_area+white_area+blue_area) 



calculate_areas(1.0) 

私の出力は次のとおりです。

Our hoist was given as : 1.000000 
Our length calculates as : 1.900000 
Width of our union is: 0.538462 
Length of our union is: 0.760000 
Area of a star is 0.001812 
Area of 50 stars is 0.090587 
Area of our flag in total is : 1.900000 
Actual WHITE AREA is 0.792126 
Actual RED AREA is 0.789231 
Expected BLUE AREA is 0.355870 
Actual BLUE AREA is 0.318644 
SumofallAreas: 1.900000 

は分散を説明できるフロートについての何かがあるのか​​、私のコード自体に問題がありますか?

*********更新されたコードPERは*****************

Pythonのフローティングを扱う問題があることが知られている
import math 
from fractions import Fraction 

def area_star(width): 
    a = 36.00 
    b = 72.00 

    radius_star = 0.0308 * width 

    a_radians = float(a) * float(math.pi)/float(180) 
    b_radians = float(b) * float(math.pi)/float(180) 

    a_sin = math.sin(float(a_radians)/float(2)) 
    b_sin = math.sin(float(b_radians)/float(2)) 

    top = a_sin*b_sin 

    c_radians = float((a+b)*math.pi)/float(180) 
    c_sin = math.sin(c_radians) 

    bottom = 0.5 * c_sin  
    return 5 * float(top)/float(bottom) * radius_star * radius_star 

def fifty_stars(width): 
    return 50 * area_star(width) 

def calculate_areas(width): 
    hoist = width 
    fly = hoist * Fraction(19,10) 

    jack_hoist = Fraction(7,13) * hoist 
    jack_fly = Fraction(76,100)*hoist 

    NUMBER_RED_STRIPES = 7 
    NUMBER_WHITE_STRIPES = 6 

    width_strip_denom = NUMBER_RED_STRIPES+NUMBER_WHITE_STRIPES 
    width_strip = Fraction(1,width_strip_denom)*hoist 

    blue_area = jack_fly * jack_hoist - fifty_stars(hoist) 
    white_area = 3 * width_strip * (fly-jack_fly)+3*width_strip*fly+fifty_stars(hoist) 
    red_area = 4 * width_strip*(fly-jack_fly)+3*width_strip*fly 




    print 'Our hoist was given as : %f' %hoist 
    print 'Our length calculates as : %f' %fly 

    print 'Width of our union is: %f' %jack_hoist 
    print 'Length of our union is: %f' %jack_fly 

    print 'Area of a star is %f'%area_star(hoist) 
    print 'Area of 50 stars is %f'%fifty_stars(hoist) 

    print 'Area of our flag in total is : %f '%(hoist*fly) 
    print 'Actual WHITE AREA is %f'%white_area 
    print 'Actual RED AREA is %f'%red_area 
    print 'Expected BLUE AREA is %f' %(hoist*fly*.1873) 
    print 'Actual BLUE AREA is %f'%blue_area 

    print 'SumofallAreas: %f' % (red_area+white_area+blue_area) 



calculate_areas(1.0) 
+0

[小数点演算が壊れて浮いていますか?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Aidan

+0

の可能性の重複問題の説明と一致する変数を使用したかどうかを監査する方が簡単です。例えば、「Wf = 1.0」とする。 –

+0

変数を更新し、分数関数を追加しました。合計は合計額になりますが、個々のBLUE_AREAはまだオフになっていますか? – Jeeves

答えて

2

ここに私の計算です。元の問題には以下のコメントに誤りがありました。 from __future__は、Python 3のように分割演算を行います。ここで、1/2 = 0.5であり、Python 2のように0ではありません。これで数学がクリーンアップされます。

また、問題文と同じ変数を使用すると、式を入力して検証するのが簡単になりました。私はKの2つのバージョンが同じ答えを出さなかったことを発見したので、問題を別々に処理して5*Kの黄金比のバージョンが私が星の領域に対して行ったのと同じ答えを得たことがわかりました。

from __future__ import division 
from math import sin,pi 

Wf = 1.0 
Lf = 1.9 * Wf 
A = Wf * Lf 
Wu = 7/13 * Wf 
Lu = .76 * Wf 
R = .0308 * Wf 
Sr = 7 
Sw = 6 
Ns = 50 
Ws = 1/(Sr+Sw) * Wf 

a = 36 * pi/180 
b = 72 * pi/180 
GR = (1 + 5**.5)/2 
K = sin(b/2)/GR**2 * (R**2) # Golden ratio version of K was correct, other was wrong. 
S = 5 * K 

Red = 4 * Ws * (Lf - Lu) + 3 * Ws * Lf 
White = 3 * Ws * (Lf - Lu) + 3 * Ws * Lf + Ns * S 
Blue = (Lu * Wu) - Ns * S # Error on problem page used (Lu - Wu) 

print('Red =',Red) 
print('White =',White) 
print('Blue =',Blue) 
print('total =',Red+White+Blue) 
print('Red = {:%}'.format(Red/A)) 
print('White = {:%}'.format(White/A)) 
print('Blue = {:%}'.format(Blue/A)) 

出力:

Red = 0.7892307692307692 
White = 0.7547841990012687 
Blue = 0.355985031767962 
total = 1.9 
Red = 41.538462% 
White = 39.725484% 
Blue = 18.736054% 
+0

ありがとうございます - これはうまくいきました。私はそれを夜に呼び出す前に2番目の式を見ていて、彼らは異なった価値を持っていることに気づいた。この変形式を補正するためにオリジナルを修正しました。異なるユースケースを除いて異なる結果をもたらす2つの数式をリストアップする理由は不明です。 – Jeeves

+0

@Jeeves私はそれが計算上の単なるエラーか、または乗算の代わりに減算を使ってBlue領域の式のような別のタイプミスであったと思う。私は間違いを判断するための最初の公式を導出しようとはしませんでした。 –

0

浮動小数点精度の問題に対処する以前のスタックは、あなたの計算はそれほど大きくオフにさせていません。

は、ここでは、Floating Point Arithmetic: Issues and Limitations

編集のためのより多くの情報です。あなたのコードにバグがあります。具体的には、出力からExpected BLUE AREA is 0.355870Actual BLUE AREA is 0.318644が大きく異なる計算を使用することが原因です。

潜在的な問題私は簡単に見分けることができます:width_unionlength_unionの両方をフラグの幅に対して計算する必要がありますか?

追加のバグがある可能性があります。コード全体に非常に多くの「魔法の数字」が含まれています(例:float(7)/float(13)0.76)。

+0

「魔法の」数字が何であるか分かりません。援助のために読めるようにしようとしました。数式は、リンクから直接的であり、概説されています。 – Jeeves

+0

「マジックナンバー」は、コードに説明がない場合に表示される数字です。 'AspectRatio = 1.9'、' StripeCount = 13'、 'RedStripes = 7'、' 'StarRadius = 0.4 * StripeHoist'などのように、一般的に一番上に定数として入力する方が良いです。 –

+0

通常は、しかし彼はちょうど運動でした - そのように過ぎ去ったようです。しかし今、私は「魔法の数字」が何であるかを知っています - そして、それらを牛のために交換しないでください! – Jeeves

0

まず、この文脈では 'length'と 'width'を参照するのは紛らわしいかもしれません。超音速学用語「ホイスト」(フラッグポールに平行な次元)と「フライ​​」(フラッグポールに垂直な次元)を使用する方が良いでしょう。

第2に、あなたの数字はオフです。あなたは高いストライプのフライのためにlength*length_unionを使用していますが、それは正しくありません。 length_unionがフライの割合ではなく、ホイストの割合ではないという事実の他に、既に倍数化されているので、再度乗算しないでください。いずれにせよ、あなたは州の飛行を望んでいませんが、ストライプのそれは、合計飛行マイナス州です。

私は残りの部分をチェックしていませんが、length*length_unionの代わりにlength-length_unionを使用すると、より良い結果が得られる可能性があります。

星を無視すると、デバッグに役立つ場合は、これらの領域が表示されます。あなたのコードのように、1.0は、その側がホイストと同じである正方形のフラグの領域です。したがって、フラグ全体は領域1.9を有する。星印

red = 513/650 (~ 0.789231) 
white stripes only = 228/325 (~ 0.701538) 
blue canton + white stars = 133/325 (~ 0.409231) 
total = (513 + 228 * 2 + 133 * 2)/650 = 1235/650 = 1.9 

ファクタリングは白青色からその一部をシフトするが、赤色(およびすべての3つの合計)が変化してはなりません。

あなたがより良い精度を希望した場合は、あなたがfractionsモジュールで正確な合理的な算術演算を使用するように切り替えることができます:

from fractions import Fraction 
hoist = 1 
fly = hoist * Fraction(19,10) 
stripe_hoist = hoist * Fraction(1,13) 
canton_hoist = 7 * stripe_hoist 
canton_fly = fly * Fraction(2, 5) 

など

+0

提案のおかげで、更新されたvar名はlength * length_unionをlength-lenght_unionに変更しました。異なる総合計を得るが、実際にはblue_area自体はまだオフになっていますか? – Jeeves

関連する問題