2012-08-17 3 views
8

irb에서 3 ** 557을 계산하려고 할 때이 문제가 발생했습니다. Ruby와 MacRuby 모두 내 Mac (OS X 10.8)에 설치되어 있습니다. 그리고 루비의 버전은 MacRuby 0.12 (루비 1.9.2)의 1.8.7입니다. 갈비뼈와 macirb는 3 ** 557의 계산에서 두 가지 다른 답변을주었습니다.Ruby의 지수화 1.8.7 잘못된 대답을 반환합니다

$ irb 
>> 3**557 
=> 54755702179342762063551440788945541007926808765326951193810107165429610423703291760740244724326099993131913104272587572918520442872536889724676586931200965615875242243330408150984753872526006744122187638040962508934109837755428764447134683114539218909666971979603 

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

(macirb의가. 권리) 그리고 뭔가 더 큰, 예를 들어, 시도 3 ** 5337, 나는 이번에도 같은 대답을했다.

그래서이 문제는 Ruby 1.8.7에서 발생합니까? 아니면 다른 방법으로 지수를 계산해야합니까?

+0

관련없는 특히,하지만 당신은 [모듈러 지수 (보고 할 수 있습니다 http://en.wikipedia.org/wiki/Modular_exponentiation)를 사용합니다. – jli

+0

1.9.3 이전의 MRI가 설치되어 있지는 않지만 올바른 결과를 제공합니다. –

+0

어떤 Mac의 정확한 모델을 사용하고 있습니까? MacPro (Xeon)에서 동일한 버전의 Ruby (1.8.7 p358)를 사용하여 이것을 재현 할 수 없습니다. 32 비트로 실행되는 오래된 1.8.6에서도 사용할 수 없습니다. –

답변

3

계산시, Ru by는 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은 long 정수로 변환되고 연산자는 long으로 처리됩니다. 걷고 워드 크기 오버플 루비는 비정상적 (Bignum이로 변환)을 * 연산자가 올바르게 작동하는지 0

주를 반환함으로써이 처리되면,이 ** 실패 여기서

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

가로 이동 최신 버전의 Ruby가이를 수정합니다. 최신 버전으로 이동할 수 없다면 Fixnum 및 **을 큰 힘으로 사용하지 마십시오.하나의 '1'로 시작해야하고 아무것도 뒤에는 모든 전원에 '10'을

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

: 자신의 지수화 방법을 쓰기

2

1.9.3을 사용하면 올바른 결과를 얻을 수 있습니다. 정말 좋은 이유가 없다면, 1.8.7이 단계적으로 제거되기 때문에 1.9.3 이상을 사용해보십시오.

Linux에서 1.8.7-p358으로 테스트 한 후에도 올바른 대답을 얻을 수 있습니다. 그것은 당신이 사용하고있는 1.8.7 버전의 버그 일 수 있습니다.

+0

감사합니다! Xcode $ ruby ​​--version ruby ​​1.8.7 (2012-02-08)과 함께 설치 될 수도 있습니다. 패치 레벨 358) [universal-darwin12.0] – Vej

+0

XCode에는 Ruby가 포함되어 있지 않지만 OS X에는 일반적으로 시스템에 일부 버전이 포함되어 있습니다. Ruby에 대해 진지한 사람이라면 누구나 'rvm'또는 'rbenv' 현재 시스템에 소유되어 있기 때문에 일반적으로 시스템 루비를 망쳐 놓는 것은 좋지 않습니다. – tadman

+0

JewelryBox를 사용하여 Ruby를 1.9.3-p194로 업데이트하고 있습니다. . – Vej

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

는 오류가 발생하지 않도록 할 수있는 또 다른 방법이 될 것 같다 그러나 제로. 루비의 ** 기능 :

10 ** 40 
=> 10000000000000000000092233720368547758080 

사용자 정의 xpnt 방법 :

루비에
xpnt 10, 40 
10000000000000000000000000000000000000000 
=> nil 
관련 문제