2016-10-19 4 views
-1

저는 간단한 자바 메서드를 사용합니다.이 메서드는 특정 숫자의 소수 구분 기호 목록을 계산한다고 가정합니다.이 Java 기능이 왜 작동하지 않습니까?

public class Factors { 



public static List<Integer> fac(List<Integer> factors, int number) { 
    if(number < 2) { 
     throw new IllegalArgumentException("Number must be greater than one"); 
    } 


    for (int i = 2; i <= number; i++) { 
     while (number%i == 0) { 
      factors.add(i); 
      number /= i; 
     } 
    } 
    return factors; 
} 
public static void main(String [] args) 
{ 
final long startTime = System.currentTimeMillis(); 

    ArrayList<Integer> factors = new ArrayList<>(); 
    System.out.println(fac(factors, 2147483647)); 

final long endTime = System.currentTimeMillis(); 
System.out.println("Total execution time: " + (endTime - startTime)); 
} 
} 

이 코드는 Integer.MAX_VALUE를 피드에 넣는 것을 제외하고는 정상적으로 작동합니다. 그 경우에 :
java.lang.OutOfMemoryError : 자바 힙 공간
처음에는 ArrayList 초기화가 메소드 내부에 있었지만 제거한 후에도 동일한 오류가 계속 발생한다고 생각했습니다.
또한, 본 :

public static List<Long> facrec2(List<Long> list, long number) { 
    if (number < 2) { 
     return list; 
    } 

    if (number == 2) { 
     list.add(2L); 
     return list; 
    } 

    for (long i = 2; i <= number; i++) { 
     while (number % i == 0) { 
      number /= i; 
      list.add(i); 
      return facrec2(list, number); 
     } 
    } 
    return null; 
} 

방법은 최대 값에 대한 동작 (정수로 서명을 변경 한 후에,도 최대 정수 값으로 작동). 둘 다의 논리는 같다고 가정하고, 두 번째의 반복적 인 구현 만이 차이를 만듭니다 ...

+0

+1. 디버깅 (또는 최소한 디버깅 시연)을 수행 할 수 있다고 생각하지만,이 버그가 이러한 예외로 이어지는 방법은 놀라 울 정도로 미묘합니다. – ruakh

+0

네,하지만 다른 사람의 함수를 모두 가지고 있고, 예제처럼, 초조하게 stackoverflow에 게시했습니다. –

+0

'[주어진 시험 횟수의 반복적이고 재귀적인 처리가] 가정되는 로직 같은'- 재귀와 함께, 당신은 결코 '숫자'의 왼쪽에있는 것을 나눈 것을 발견 한 후에'i'를 증가시키지 않고 (그리고 다시 확인하십시오). – greybeard

답변

1
for (int i = 2; i <= number; i++) { 

문제는 여기에 있습니다. number == Integer.MAX_VALUE이 루프는 절대로 종료되지 않습니다. iInteger.MAX_VALUE이되면 다음 증가분은 매우 음수 인 Integer.MIN_VALUE으로 설정하고 루프는 계속 실행되므로 목록에 계속 추가되어 메모리가 부족합니다.

가장 간단한 해결책은 루프 조건을 <으로 변경하고 number이 원래 값을 별도로 유지하는 경우 (즉, number이 소수 인 경우)를 처리하는 것입니다. 또한 루프를 끝내면 number == 1을 종료 할 수 있습니다.

+1

+1. 'i'가'Integer.MAX_VALUE'가되면'number'가'1'로 설정됩니다. 그러나 그 이후에'i'는'Integer.MIN_VALUE'로 설정되기 때문에 여전히'number'보다 작습니다. 그리고 나서'i'는 결국'1'에 도달합니다.이 때'number % i == 0'은 영구적으로 true이므로 메모리가 부족할 때까지 임의로 많은 '1'이 채워집니다. 'Integer.MAX_VALUE'가 소수 일 때가 불행합니다. :-) – ruakh

+0

네, 정확히 이런 일이 일어납니다. 첫 번째 함수는 yield [2147483647, -1] 일 때 변경되지만, 예를 들어 120은 잘못된 응답을 반환하고 2, 3, 4, 5를 반환합니다 (4는 소수가 아닙니다). 그래서 중요한 것은, 당신이 제안한 기능이 필요합니다. 두 번째는 괜찮을 것 같습니다. –

+0

제안 된 'while/if'변경 사항은 지금 삭제되지 않았으므로 올바르지 않습니다. 프라임 요소를 얻으려면'while'이 필요합니다. – EJP

0

이 루프는 종료되지 않습니다. 카운터 i가 Integer.MAX_VALUE에 도달하면 롤오버됩니다. 루프 상태에서 동등 함을 허용하면 안됩니다.

관련 문제