2012-08-17 35 views
8

當我嘗試在irb中計算3 ** 557時遇到此問題。 Ruby和MacRuby都安裝在我的Mac(OS X 10.8)中。和紅寶石的版本是1.8.7,MacRuby 0.12(紅寶石1.9.2)。 肋骨和macirb在計算3 ** 557時給了我兩個不同的答案。 (macirb's是對的。)Ruby 1.8.7中的求冪指數返回錯誤的答案

$ irb 
>> 3**557 
=> 54755702179342762063551440788945541007926808765326951193810107165429610423703291760740244724326099993131913104272587572918520442872536889724676586931200965615875242243330408150984753872526006744122187638040962508934109837755428764447134683114539218909666971979603 

$ macirb 
irb(main):001:0> 3**557 
=> 57087217942658063217290581978966727348872586279944803346410228520919738045995056049600505293676159316424182057188730248707922985741467061108015301244570536546607487919981026877250949414156613856336341922395385463291076789878575326

然後我嘗試了更大的東西, 3 ** 5337,這次我得到了同樣的答案。

那麼,這是Ruby 1.8.7中的一個錯誤,還是我應該用另一種方式來計算指數?

+0

無關的紅寶石明確,但你可能想看看[模冪(http://en.wikipedia.org/wiki/Modular_exponentiation)取決於你對結果做了什麼。 – jli 2012-08-17 16:46:26

+0

我沒有安裝MRI 1.9.3之前的版本,但是確實給出了正確的結果。 – 2012-08-17 17:36:21

+0

你正在使用哪種確切型號的mac?我無法在MacPro(Xeon)上使用相同版本的Ruby(1.8.7 p358)重現此操作。我也不能在32位的舊版1.8.6上運行。 – 2012-08-17 18:16:52

回答

3

當計算時,Ru當數字超出Fixnum的範圍時,應該由Fixnum轉換爲Bignum。對於舊版本的Ruby,這失敗**操作:

$ ruby --version 
ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0] 
$ irb 
>> 2 ** 62 
=> 4611686018427387904 
>> 2 ** 63 
=> -9223372036854775808 
>> 2 ** 64 
=> 0 

如果它失敗取決於架構的字大小。本例中的iMac上有64位字。在內部,Fixnum被轉換爲一個長整數,並且操作符被處理很長時間。多頭溢出,在字的大小,和Ruby是通過返回0

注意,*操作正常工作笨拙地處理這個(轉換爲Bignum的),其中**失敗:

>> a = 2 ** 62 
=> 4611686018427387904 
>> 2 ** 63 
=> -9223372036854775808 
>> a * 2 
=> 9223372036854775808 
>> 2 ** 64 
=> 0 
>> a * 4 
=> 18446744073709551616 

移動到一個較新版本的Ruby將解決此問題。如果你不能移動到更新的版本,那麼避免使用Fixnum和**大功率。

2

使用1.9.3會產生正確的結果。除非你有一個非常好的理由,否則試着使用1.9.3或更高版本,因爲1.8.7正在被淘汰。

值得注意的是,在Linux上測試1.8.7-p358後,我也得到了正確的答案。它可能是您使用的特定版本1.8.7中的一個錯誤。

+0

謝謝!它可能與Xcode 一起安裝$ ruby​​ --version ruby​​ 1.8.7(2012-02-08 patch-level 358)[universal-darwin12.0] – Vej 2012-08-17 17:46:58

+0

XCode不包含Ruby,但OS X通常包含系統的一些版本,儘管任何認真對待Ruby的人都會使用'rvm'或'rbenv'將其切換爲更多目前的版本,一般來說這不是一個好主意,因爲它是由系統技術所有,並且可以隨時通過Apple補丁修改系統Ruby。 – tadman 2012-08-18 00:38:25

+0

現在我使用JewelryBox將Ruby更新爲1.9.3-p194 。 – Vej 2012-08-18 04:07:50

1

這絕對是一個錯誤。這可能取決於處理器和/或編譯選項。

如果它被this commit修復,我不會感到驚訝。

正如其他人所說,只有安全修補程序現在使其達到1.8.7,所以升級到1.9.3。

0

這與明確指數無關。我認爲這與代表性所需的從63位到64位的轉換有某些關係,儘管這似乎不是100%一致的。

>> 19**14 
=> 799006685782884121 
>> 19**15 
=> -3265617043834753317 
>> (19**14)*19 
=> -3265617043834753317 

>> 2**64-1 
=> -1 
>> 2**64 
=> 0 
>> 0x7fffffffffffffff 
=> 9223372036854775807 

>> 0x8000000000000000 
=> 9223372036854775808 

另外:在運行32位模式IRB(arch -i386 irb),我沒有看到這個在這一點上,而是更早:

>> 19**15 
=> 15181127029874798299 
>> 2**31 
=> -2147483648 
0

編寫自己冪方法似乎是另一種方式來做到這一點不產生錯誤:

def xpnt(base, exponent) 
    sum = base 
    while exponent >= 2 
     sum = sum * base 
     exponent -= 1 
    end 
    puts sum 
end 

「10」的權力應與一個單一的「1」開始,被後面什麼都沒有但是零。 Ruby的**功能:

10 ** 40 
=> 10000000000000000000092233720368547758080 

定製xpnt方法:

xpnt 10, 40 
10000000000000000000000000000000000000000 
=> nil