2016-06-23 4 views
0

Пытается решить Building Skills with Python, область флага. Я пытаюсь решить для синей области, но я ухожу примерно на 2%. Кроме того, когда я суммирую другие области, сумма не равна площади самого флага. Мой код выглядит следующим образом:Python - Area of ​​Flag

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 

Есть ли что-то о Float, которые могли бы объяснить дисперсию или проблема в самом моем коде?

********* ОБНОВЛЕНО КОД НА ПРЕДЛАГАЕТ *****************

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, а не 0, как в Python 2. Это очищает математику.

Кроме того, использование тех же переменных, что и описание проблемы, упростило ввод и проверку формул. Я обнаружил, что две версии K не дали того же ответа, поэтому независимо от проблемы работали и обнаружили, что версия с золотым соотношением 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

Спасибо - это сработало. Я смотрел на вторую формулу, пока не назвал ее ночью, и заметил, что у них разные ценности. Модифицировал мой оригинал, чтобы компенсировать эту формулу. Не уверен, почему они перечисляют две формулы, которые дают разные результаты, если не используются разные варианты использования. – Jeeves

+0

@ Jeeves Я думаю, что это была просто ошибка в вычислении, или, может быть, другая опечатка, подобная формуле Blue area, с использованием вычитания вместо умножения. Я не пытался получить первую формулу для определения ошибки. –

-3

Python, как известно, вопросы, связанные с плавающей точечные операции.

Здесь больше информации для вас Floating Point Arithmetic: Issues and Limitations

Edit: Также предыдущий стек адресация тот же/аналогичный вопрос Python rounding error with float numbers [duplicate]

+0

Если вы ссылаетесь на аналогичный пост, отметьте его как дубликат – Li357

+0

Он буквально говорит дубликат в названии – Aidan

+0

тем более, что пометить это сообщение как дубликат исходного сообщения – Li357

0

Плавающие вопросы точности точек не вызывают ваши расчеты настолько значительно прочь. У вас только что есть ошибки в коде. В частности, с вашего вывода Expected BLUE AREA is 0.355870 и Actual BLUE AREA is 0.318644 вызваны использованием существенно разных вычислений.

Потенциальная проблема, которую я могу определить с помощью быстрого обзора: Должны ли рассчитываться как width_union, так и length_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*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 

Факторинг в звездах будет переложить часть, что от синего до белого, но красный (и сумма всех трех) не должно измениться.

Если вы хотите более высокую точность, вы можете переключиться на использование точной рациональную арифметику с 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

Спасибо за предложения - обновленные имена переменных изменили длину * length_union на length-lenght_union. Получая разную общую сумму, но фактический blue_area сам по себе все еще выключен ??? – Jeeves