2011-08-08 1 views
-1

마지막 요소를 찾는 것이 문제입니다. 그것은 잘 작동 정수 유형. Int 형식으로 오버플로하지만 Int64를 시도 할 때 가비지 수집기가 작동하지 않는 것으로 보입니다.Int64를 사용하는 haskell에서의 메모리 사용

module Main (main) where 
import Data.Int 
import System.Environment 

getNum :: Int -> Int64 

merge [] s2 = s2 
merge s1 [] = s1 
merge (s1:s1s) (s2:s2s) 
     | s1 < s2 = s1 : (merge s1s (s2:s2s)) 
     | s1 > s2 = s2 : (merge (s1:s1s) s2s) 
     | otherwise = s1 : (merge s1s s2s) 

scaleStreams scale = map $ (*) scale  

getNum n = s_3_56!!n 
    where s_3_56 = 1:(merge (scaleStreams 2 s_3_56) 
        (merge (scaleStreams 3 s_3_56) 
        (scaleStreams 5 s_3_56))) 

main = do 
    snum:_ <- getArgs 
    putStrLn $ show $ getNum (read snum) 

UPD. 수입 한 Data.Int. 그리고 100,000,000 개의 요소가 필요합니다. Int64를 사용하면 응답을 멈추거나 프로세서 사용을 중지합니다.

어쩌면 내가 ghc에 필요한 키를 필요로하므로 요소를 정리할 필요가 없습니다.

이 모두가 벤치마킹에 관한 것이므로 Integer라는 것이 더 명확해야합니다.

+1

어떤 오류가 발생합니까? 'Data.Int' 가져 오기 시도 - Intlude는 Prelude에 없습니다. 또한 Integer (Prelude!에 있음)를 사용하면 오버플로가 발생하지 않습니다. 저는 GHCi에서'getNum 200000'이'4480327901140333639941336854183943340032000000000'과 같습니다 :-) – yatima2975

+1

예,'Integer'를 사용하면 좋은 기본값입니다. Integer가 병목으로 판명되면 다른 유형으로 만 이동하십시오. – augustss

+0

downvotes에 대한 특별한 이유가 있습니까? 질문자가 문제가 무엇인지에 대해 착각하고 있다고 생각하지 않거나 강한 영어 명령을 지키지 않으면 downvotes가 보증됩니다. – gatoatigrado

답변

0

당신은 당신의 코드 라인

import Data.Int 

이 필요합니다.

6

숫자의 크기에서 Int 또는 Int64으로 오버플로 할 것입니다. 이것은 merge의 비교를 망칠 것입니다.

임의의 크기의 Integer을 사용하도록 변경하면 알고리즘이 대략 선형의 시간 및 공간 복잡성을 나타내는 것으로 나타납니다.

*Main> :set +s 
*Main> getNum 10 
15 
(0.05 secs, 15791376 bytes) 
*Main> getNum 100 
1600 
(0.04 secs, 15805848 bytes) 
*Main> getNum 1000 
51840000 
(0.05 secs, 16849584 bytes) 
*Main> getNum 10000 
288555831593533440 
(0.10 secs, 26238720 bytes) 
*Main> getNum 100000 
290237644800000000000000000000000000000 
(0.39 secs, 149698872 bytes) 
*Main> getNum 1000000 
519381797917090766274082018159448243742493816603938969600000000000000000000000000000 
(3.57 secs, 1440858488 bytes) 
*Main> getNum 10000000 
16244249195502759967226308067328000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 
(36.49 secs, 15318940632 bytes) 
*Main> getNum 100000000 
18140183964781799067475734441903054103752590419562119585784549199072397211943448001454797147212334274622985787416351057209969867746413217762757199393702760885526212114105820164278263467669252072928640885180135225440700708077201852574944496154785156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 
(398.26 secs, 173628505536 bytes) 

내가 알 수있는 한 가비지 수집기가 올바르게 작동하는 것 같습니다. 100,000,000의 실행은 총 173GB의 메모리를 할당하지만, 한 번에 관찰 된 최고 피크는 약 900MB였습니다.

+0

난 그냥 Int64와 함께 시간을 측정해야합니다 데이터 형식이 그것의 C# 버전에서 동일합니다, 사촌 내가 C#은 BigInteger 및 haskell Integer를 사용하는 시간을 측정 할 수 없습니다. – rudzon

+1

@rudzon : 그렇다면 오버플로가 프로그램 작동을 방해하므로 더 작은 입력으로 테스트해야합니다. Int64에 들어갈 수있는 최대 숫자는 9,223,372,036854775807이므로'getNum 100000'도 그걸지나갑니다. – hammar

+0

고마워,하지만 난 오버플로 걱정하지 않아 : P는 단지 Int64를 사용하여 계산 속도를 측정하고자합니다. – rudzon