【问题标题】:Python - Area of a FlagPython - 旗帜区域
【发布时间】:2016-06-23 04:07:36
【问题描述】:

试图解决Building Skills with Python,标志区域。我正在尝试解决蓝色区域,但是我偏离了大约 2%。此外,当我将其他区域加起来时,总和不等于旗帜本身的面积。我的代码如下:

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)

【问题讨论】:

  • 如果您使用与问题描述相匹配的变量,审计会更容易。以Wf = 1.0 为例。
  • 更新变量,添加分数函数。现在总和到正确的金额,但个别 BLUE_AREA 仍然关闭??
  • 请避免用修改后的版本替换您的原始代码!它使现有答案变得无关紧要,整个问题页面令人困惑。您可以在原始版本之后添加新版本,并说明它是基于某些给定答案和/或 cmets 的修订版本。
  • 大部分幻数都可以推导出来。例如,72º 的角度 B 只是圆的 1/5(因为星星有 5 个点),而角度 A 只是 B 的一半。唯一需要的参数是旗帜的纵横比(1.9 fly:葫芦),州的飞行(国旗飞行的40%)和星星的大小(直径= 80%的一条条纹),以及有13条条纹的事实,顶部和底部是红色的,州跨越前 7 名。

标签: python precision area


【解决方案1】:

这是我的计算。原始问题在下面的 cmets 中有错误。

注意:from __future__ 使除法工作像 Python 3 一样,其中 1/2 = 0.5,而不是像 Python 2 中的 0。这会清理数学。

此外,使用与问题陈述相同的变量可以更轻松地输入和验证公式。我发现两个版本的 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%

【讨论】:

  • 谢谢 - 这工作。在我打电话给它之前,我正在查看第二个公式,并注意到它们得到了不同的值。修改了我的原件以补偿这个变体公式。不知道为什么他们列出了两个产生不同结果的公式,除非不同的用例。
  • @Jeeves 我认为这只是计算中的错误,或者可能是另一个错字,例如使用减法而不是乘法的蓝色区域公式。我没有尝试推导出第一个公式来确定错误。
【解决方案2】:

首先,在此上下文中提及“长度”和“宽度”可能会造成混淆;最好使用旗帜学术语'hoist'(平行于旗杆的尺寸)和'fly'(垂直于旗杆的尺寸)。

其次,您的号码已关闭。您正在使用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)

等等

【讨论】:

  • 感谢您的建议-更新的 var 名称将 length*length_union 更改为 length-lenght_union。得到不同的总和,但实际的 blue_area 本身仍然关闭??
【解决方案3】:

浮点精度问题不会导致您的计算出现如此显着的偏差。您的代码中刚刚出现错误。具体来说,根据您的输出,Expected BLUE AREA is 0.355870Actual BLUE AREA is 0.318644 是由使用显着不同的计算引起的。

一个潜在问题我可以通过快速查看来识别:width_unionlength_union 是否都应该相对于标志的宽度进行计算?

您可能还有其他错误,很难看到代码中散布着如此多的“神奇数字”......(例如float(7)/float(13)0.76)。

【讨论】:

  • 不确定什么是“神奇”数字——试图使其可读以寻求帮助。公式直接来自链接和概述。
  • “幻数”是在代码中没有解释的数字。通常最好将它们作为常量输入到顶部,例如 AspectRatio = 1.9StripeCount = 13RedStripes = 7StarRadius = 0.4 * StripeHoist 等。
  • 通常我会把常量放在最前面,但他只是一个练习——这样似乎有点过头了。但现在我知道什么是“神奇数字”了——而不是用它们来换牛!
【解决方案4】:

众所周知,Python 在处理浮点运算时存在问题。

这里有更多信息给你Floating Point Arithmetic: Issues and Limitations

编辑: 还有一个以前的堆栈解决了相同/相似的问题Python rounding error with float numbers [duplicate]

【讨论】:

  • 如果您链接了类似/相同的帖子,请标记为重复
  • 字面意思是重复的名字
  • 更有理由将此帖子标记为原始帖子的副本
  • 与其投反对票,不如自己编辑名称。富有成效
  • 我没有投反对票哈哈。不要以为我有。我希望您编辑和改进答案
猜你喜欢
  • 1970-01-01
  • 2012-10-06
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 2012-05-09
  • 2011-05-20
相关资源
最近更新 更多