Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2.7中四舍五入时分数精度较低_Python_Python 2.7_Rounding - Fatal编程技术网

Python 2.7中四舍五入时分数精度较低

Python 2.7中四舍五入时分数精度较低,python,python-2.7,rounding,Python,Python 2.7,Rounding,大家好,我对python非常陌生,这是我的第一个项目。我正在创建一个计算器,当我输入一个圆的周长时,它会为我计算直径。比如摩托车上的把手,但没有把手 我让它工作,但我真的需要它不那么准确,比如可能四舍五入到最接近的1/8。如果我输入2.75,它工作完美,但如果我输入2.76,它会给出疯狂的分数。我仍然希望它读7/8,直到它超过1.0的一半 这是我到目前为止所做的一切。你能提供的任何帮助都将是巨大的 from fractions import Fraction print "Do you wis

大家好,我对python非常陌生,这是我的第一个项目。我正在创建一个计算器,当我输入一个圆的周长时,它会为我计算直径。比如摩托车上的把手,但没有把手

我让它工作,但我真的需要它不那么准确,比如可能四舍五入到最接近的1/8。如果我输入2.75,它工作完美,但如果我输入2.76,它会给出疯狂的分数。我仍然希望它读7/8,直到它超过1.0的一半

这是我到目前为止所做的一切。你能提供的任何帮助都将是巨大的

from fractions import Fraction

print "Do you wish to calculate the Diameter or Radius from a perimeter measurement? Type 'd' or 'r'"
var = raw_input("Please type 'd' or 'r'")


if var == 'd':
    print "Now type the perimeter measurement for the diameter you would like calculate."
    cir = float(raw_input())
    answer = cir/3.1415926535
    rnd = round(answer, 3 )
    frac = Fraction(rnd).limit_denominator()
    print rnd
    print "The diameter of a %s perimeter is" % cir, frac
elif var == 'r':
    print "Now type the perimeter measurement for the Radius you would like to calculate."
    cir = float(raw_input())
    answer = cir/3.1415926535/2
    print "The Radius of a %s perimeter is" % cir, answer 
else:
    print "Error: You did not type 'd' or 'r' Please run again"

你可以把它四舍五入到最接近的1/8

In [1]: from fractions import Fraction

In [14]: Fraction(round(2.6*8)/8).limit_denominator()
Out[14]: Fraction(21, 8)

In [4]: Fraction(round(2.75*8)/8).limit_denominator()
Out[4]: Fraction(11, 4)

In [5]: Fraction(round(2.9*8)/8).limit_denominator()
Out[5]: Fraction(23, 8)

如果你需要相同的分母,这很简单

denominator = 8
rnd = round(answer * denominator)
frac = Fraction(int(rnd), denonimator)

以前所有的方法都使用了
round(x*8)/8
方法,这是错误的;当然,当我赶时间的时候,我有时(不经常)使用它,但这是一种错误的方法

方法1(最正统的)

根据连分数理论,2.76有四个最佳近似值,即:

2, 3, 11/4, 69/25
你可以说11/4和22/8是一样的,但你不能期望它对任何数字都是这样。以圆周率为例,
round(3.1415926*8)/8
是25/8,与22/7相比,这是一个非常差的近似值:22/7实际上将Pi近似为1/8,但甚至更好(虽然比25/8简单)原始海报希望接近1/8。看看下面三个分数:22/7、25/8、314/100;所有的圆周率都近似于1/8,但您会选择哪一个(可能是第一个;现在:第一个不仅是三个分数中最简单的;它也是最精确的)?做得比22/7好的最简单分数跳到1e-4以下作为其精度(即333/106)

此外,如果你想接近0.5,你不能满足于4/8!当然,
分数
模块可能会在初始化时取消它,但这无论如何是一个非常糟糕的迹象:您的方法不希望产生类似4/8的结果,即使是作为中间步骤

一个笑话:拿0.33333。。。并尝试
round(x*8)/8
方法;你会发现3/8近似于0.33333。。。到1/8,这当然是真的,但是。。。如何礼貌地说

看看下面的函数;您可以放心地使用它来近似计算一个数字:

from fractions import Fraction                                              

def rationalize(x, maxden=1000):
    p0, p1 = 0, 1
    q0, q1 = 1, 0
    a = int(x) if x >= 0 else int(x-1)
    while q1 <= maxden:
        p = a*p1 + p0
        q = a*q1 + q0
        p0, p1 = p1, p
        q0, q1 = q1, q
        if x==a:
            if q1 <= maxden: return Fraction(p1, q1)
            else: return Fraction(p0, q0)
        x = 1/(x-a)
        a = int(x)
    return Fraction(p0, q0)
从分数导入分数
def合理化(x,maxden=1000):
p0,p1=0,1
q0,q1=1,0
如果x>=0,则a=int(x)否则int(x-1)

而这是一个非常糟糕的想法;如果你试着将圆周率四舍五入到最接近的1/8,你会得到25/8,与22/7相比,这是一个非常糟糕的近似值。请看下面我的答案。问题是我让它工作了,但我真的需要它2不太精确,比如可能四舍五入到最接近的1/8。请注意,数学家几个世纪以来一直在花费时间建立理论,解释为什么分母小于8的圆周率应该是22/7,为什么不使用他们的工具?顺便说一句,22/7实际上将Pi近似为最接近的1/8(甚至更好)…我同意你的看法。但这里提出的问题实际上是想构建这样的东西,将数字四舍五入到最接近的1/8。这里的
limit\u分母
调用是多余的:它们不会改变结果。这是一个非常糟糕的主意;如果你试着将圆周率四舍五入到最接近的1/8,你会得到25/8,与22/7相比,这是一个非常糟糕的近似值。见下面我的答案。@Baruchel如果OP使用的是单位为1/8英寸的标尺(是的,当单位为毫米时,这真是个坏主意!),那么1/7单位的结果对他来说是完全无用的。它可能会打乱你内心的数学家,但一个有用的结果可能比1/100量级的数字精度更重要。@tripleee为什么“打乱”?在某种程度上我同意你的观点;但我相信,如果我们使用计算机,我们的思维方式也不会完全与使用标尺时的思维方式相同。您能否提及函数(
rationalize()
)是否总是产生最佳近似值,以及在什么意义上它是最佳的?你有解释这个理论的链接吗?@J.F.Sebastian对!我编辑了我的帖子并添加了链接。你好,我想你没抓住重点。我认为OP希望结果是1/8(1/8,1/4,1/2)的倍数。22/7是圆周率的最佳近似值,当然-我在那所学校学过-但这不是我要问的问题。@SiHa Hummm。。。也许你是对的,但我重新阅读了这个问题,尝试了代码,最终保持了我的理解。如果用户键入:1.0472,我的答案将导致“直径为1/3”,而其他方法将导致“直径为3/8”(确切答案为0.33333 4…)。公平地说,即使是最简单的输入“1”也会导致这种情况。别忘了他/她正在编写与用户的界面;用户希望读取最简单的分数(如果也是最准确的话)。注意。@Baruchel:您是否知道
分数
类型已经有了一个
极限_分母
方法,可以为给定分母界生成尽可能最佳的近似值?您是专门寻找分母幂为2的小分数(在测量英寸时很常见)还是任何“简单”的分数分数最接近匹配?例如,您是否希望将0.35这样的值四舍五入到3/8(不准确,但易于测量)或1/3(“更简单”且更准确,但在大多数标尺上不适用)?或者你总是想要一个八分之一的值,即使它可以进一步减少——2/8比1/4更可取吗?