2014-11-09 4 views
0

numberOf 3 또는 numberOf integer> 2를 호출 할 때 코드가 여기에 있습니다. 오류 - C 스택 오버플로가 발생했습니다. 내 코드는 n> 2에서 이진수로 2^(n-2) (2^n) -1 사이의 숫자를 변경하고 연속 0인지 아닌지를 확인해야합니다. 만약 거기에 카운트가없고 +1이 없다면.내 재귀 함수에서 스택 오버플로

numberOf :: Integer -> Integer 
numberOf i = worker i 

worker :: Integer -> Integer 
worker i 
    | (abs i) == 0 = 0 
    | (abs i) == 1 = 2 
    | (abs i) == 2 = 3 
    | otherwise = calculat (2^((abs i)-2)) ((2^(abs i))-2) 

calculat :: Integer -> Integer -> Integer 
calculat ab bis 
    | ab == bis && (checker(toBin ab)) == True = 1 
    | ab < bis && (checker(toBin ab)) == True = 1 + (calculat (ab+1) bis) 
    | otherwise = 0 + (calculat (ab+1) bis) 

checker :: [Integer] -> Bool 
checker list 
    | list == [] = True 
    | 0 == head list && (0 == head(tail list)) = False 
    | otherwise = checker (tail list) 

toBin :: Integer -> [Integer] 
toBin n 
    | n ==0 = [0] 
    | n ==1 = [1] 
    | n `mod` 2 == 0 = toBin (n `div` 2) ++ [0] 
    | otherwise = toBin (n `div` 2) ++ [1]  

테스트 :

numberOf 않음 3 : 5 (13)
numberOf 10 (144)
numberOf (-5) (5)
numberOf calculat IN (13)

+0

(+1) 스택 오버 플로우에 대한 :


당신은 또한 당신이 불필요한 혼란을 가지 어려운 방법을 수행하거나 추가 한 많은 장소가 실질적으로 최대 코드를 청소 수 표제. –

답변

5

문제는 calculat의 당신의 정의에 자리 잡고 있습니다. ab == bisab < bis의 사례가 있지만 calculat이라고하는 유일한 장소는 2^(abs i - 1)2^(abs i - 2) 인 인수가 worker입니다. 첫 번째 숫자 (ab)는 항상 두 번째 숫자 (bis)보다 크므로 ab < bis을 확인하는 것은 매우 어리 석습니다. 그렇지 않은 경우에는 ab을 증가시켜이 함수가 절대로 종료되지 않도록하십시오. otherwise = calculat ab (bis + 1)을 대신 사용하셨습니까? 에

-- Remove worker, having it separate from numberOf was pointless 
numberOf :: Integer -> Integer 
numberOf i 
    | i' == 0 = 0 
    | i' == 1 = 2 
    | i' == 2 = 3 
    -- Lots of unneeded parentheses 
    | otherwise = calculat (2^(i' - 1)) (2^i' - 2) 
    -- Avoid writing the same expression over and over again 
    -- define a local name for `abs i` 
    where i' = abs i 

calculat :: Integer -> Integer -> Integer 
calculat ab bis 
    -- Remove unneeded parens 
    -- Don't need to compare a boolean to True, just use it already 
    | ab == bis && checker (toBin ab) = 1 
    | ab < bis && checker (toBin ab) = 1 + calculat (ab + 1) bis 
    -- 0 + something == something, don't perform unnecessary operations 
    | otherwise      = calculat (ab + 1) bis 

-- Pattern matching in this function cleans it up a lot and prevents 
-- errors from calling head on an empty list 
checker :: [Integer] -> Bool 
checker []  = True 
checker (0:0:_) = False 
checker (_:xs) = checker xs 

-- Again, pattern matching can clean things up, and I find an in-line 
-- if statement to be more expressive than a guard. 
toBin :: Integer -> [Integer] 
toBin 0 = [0] 
toBin 1 = [1] 
toBin n = toBin (n `div` 2) ++ (if even n then [0] else [1]) 
+0

2^((abs i) -2)와 (2^(abs i)) - 2 사이의 모든 숫자를 확인하고 싶습니다. 이것은 내 거짓이었다. 죄송합니다. 이제이 문제가 생겼습니다 : 프로그램 오류 : 패턴 일치 실패 : head [] – Mert

+0

이것은'head (tail list)'를 호출하고'list'는 하나의 요소 만 가질 수 있기 때문입니다. 일반적으로,'head'와'tail'을 사용하여 패턴 매칭을 선호해야합니다. 코드를 정리하기 위해 내 게시물을 편집 할 것입니다. – bheklilr

+0

대단히 고맙습니다. 메신저는 아직 haskell에서 초보자입니다. 나는 어떤 코드가 불필요하거나 필요하다는 것을 아직 모른다. 코드에 대한 조언을 주셔서 다시 한 번 감사드립니다. – Mert

0

ab == bis 인 경우 검사기가 false를 반환하면 함수에서 반환 할 수 없습니다.

방법에 대해 :

| ab >= bis && (checker(toBin ab)) == True = 1 
| ab < bis && (checker(toBin ab)) == True = 1 + (calculat (ab+1) bis) 
| otherwise = 0 + (calculat (ab+1) bis) 
| ab >= bis = 0 
| ab < bis == True = 0 + (calculat (ab+1) bis) 
| otherwise = 0 + (calculat (ab+1) bis) 
+0

ab == bis 및 checker false 조건을 추가했지만 여전히 스택 오버플로가 발생했습니다. – Mert

+0

이 있습니다. 프로그램 오류 : 패턴 일치 실패 : head [] with this code | ab> = bis && (검사기 (toBin ab)) == True = 1 | ab Mert

관련 문제