2010-01-10 82 views
6

是否有一个纯粹的python实现fractions.Fraction支持long s作为分子和分母?不幸的是,指数似乎被编码为返回一个浮点数(ack !!!),这应该至少支持使用decimal.Decimal具有十进制精度的分数

如果没有,我想我可以制作一个库的副本,并尝试用Decimal替换float()出现的地方,但我宁愿以前被别人测试过的东西。

下面是一个代码示例:

base = Fraction.from_decimal(Decimal(1).exp()) 
a = Fraction(69885L, 53L) 
x = Fraction(9L, 10L) 

print base**(-a*x), type(base**(-a*x)) 

导致0.0 <type 'float'>如果答案应该是一个非常小的小数。

更新:我现在有以下解决方法(假设,对于** b,这两者都是分数;当然,当exp_是浮点数或本身时,我需要另一个函数一个十进制):

def fracpow(base, exp_): 
    base = Decimal(base.numerator)/Decimal(base.denominator) 
    exp_ = Decimal(exp_.numerator)/Decimal(exp_.denominator) 

    return base**exp_ 

其中给出了答案4.08569925773896097019795484811E-516。如果没有额外的功能,我还是会有兴趣去做这件事(我猜如果我足够使用Fraction类,我会发现其他花车在我的结果中工作)。

+0

当我做分数。分数(11,17)** 2我得到分数。分数(121,289)。你得到了什么? – 2010-01-11 00:12:23

+0

尝试类型(fractions.Fraction(11,17)** 2.1) – Noah 2010-01-11 00:15:07

+0

IMO,你看到的行为是正确的,但不是你想要的。由于指数是一个浮点数,所以事物转换为浮点数是合理的。现在,如果指数是分数(21,10),那会更有趣...... – 2010-01-11 00:46:30

回答

6

“提高到电源”还没有结束的有理数(不同于通常的四次运算)的闭合操作:没有有理数r使得r == 2 ** 0.5。据传说,毕达哥拉斯(从他的定理中,这个事实如此简单)就让他的门徒Hippasus因证明这一点的可怕罪行而被杀害;看起来像你同情毕达哥拉斯所谓的反应;-),考虑到你对“应该”的奇怪使用。

Python的分数是准确的,所以不可避免地会出现这样的情况,即将分数提高到另一分数的功率将绝对是不能返回分数作为其结果;和“应该”不能合理地应用于数学上的不可能性。

所以你可以做的最好的是大约你想要的结果,例如,通过得到一个不是精确分数的结果(浮点数通常被认为是足够的),然后用分数进一步逼近它。大多数现有的纯Python实现(有很多rationals.py文件在网络中找到;-)更喜欢根本不实施**运营商,但当然,没有什么能阻止你在自己的实现中做出不同的设计决定! )

+0

这当然是数学上正确的,但我使用Fraction类的原因是因为我想要高数值准确性,我试图更新代码别人写了使用clnum库。由于Fraction很乐意花费很长的时间作为分子或分母,因此在求幂运算时它应该能够返回一个十进制数似乎是公平的。现在,如果我能弄清楚fracpow(0,0)是否应该定义为1,或者如果这是代码中的错误! – Noah 2010-01-11 01:03:02

+1

@Noah,在这里无法真正帮助你使用纯Python代码,因为对于这样的任务,我总是使用'gmpy';但gmpy.mpq不允许带小数指数的不精确根(本例中是_my_设计决定),所以我会通过高精度浮点数(gmpy.mpf,就我的情况而言),就像使用Decimal(它们也是浮点数,只是十进制数而不是二进制数,用SW而不是HW实现,并且可以根据需要设置高精度 - gmpy.mpf是相似的,但是二进制而不是十进制)。 – 2010-01-11 01:27:05

+0

来自exp的数值近似值的误差通常会大于接近近似结果与浮点数的误差。 – 2010-01-11 01:27:07

0

您可以为不使用浮点指数的分数编写自己的“pow”函数。那是你想要做什么?

这会将一小部分提高到一个整数次方,并回落到浮动状态。

def pow(fract, exp): 
    if exp == 0: 
     return fract 
    elif exp % 2 == 0: 
     t = pow(fract, exp//2) 
     return t*t 
    else: 
     return fract*pos(fract, exp-1) 
+0

嗯,最好_some_碱情况下终止递归最终! - ) – 2010-01-11 00:43:11