2010-01-10 116 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