Search code examples
pythonprecisionarea

Python - Area of a Flag


Trying to solve Building Skills with Python, area of a flag . I am trying to solve for the blue area however I'm off by about 2%. Additionally when I total up the other areas, the total does not equal the area of the flag itself. My code is as follows:

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)

My output is:

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

Is there something about Float that could explain the variance or is the problem in my code itself?

*********UPDATED CODE PER SUGGESTS*****************

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)

Solution

  • Here's my calculation. The original problem had errors noted in comments below.

    Note: The from __future__ makes division work like Python 3, where 1/2 = 0.5, not 0 like in Python 2. This cleans up the math.

    Also, using same variables as the problem statement made it easier to enter and verify the formulas. I found the two versions of K didn't give the same answer, so worked the problem independently and found the golden ratio version of 5*K got the same answer I did for the area of a star.

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

    Output:

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