System.out.println이 사용되지 않는 한 끝없는 루프가 종료됩니다.
나는 한 코드의 간단한 비트했다 생각 때문에 무한 루프로 x
항상 성장한다 j
.
int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
x = x + y;
}
System.out.println(y);
그러나 y
모든 것이 발표되지 않았습니다. 이유를 알 수 없습니다. 그러나 다음과 같은 방식으로 코드를 가질 때 :
int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
x = x + y;
System.out.println(y);
}
System.out.println(y);
끝없는 루프가되고 이유를 모르겠습니다. 자바는 무한 루프를 인식하고 첫 번째 상황에서는 건너 뛰지 만 두 번째 상황에서는 메소드 호출을 실행해야 예상대로 작동합니까? 혼란스러워 :)
두 가지 예 모두 끝이 없습니다.
문제는 int
Java (또는 거의 다른 공통 언어) 의 유형 제한입니다 . 의 값이 x
도달하면 0x7fffffff
양수 값을 추가하면 오버플로가 발생하고 x
는 음수가되어보다 처리 j
됩니다.
첫 번째와 두 번째 루프의 차이점은 내부 코드가 훨씬 더 많은 시간이 걸리고 x
오버플로 가 거의 때까지 몇 분 정도 걸릴 수있는 것입니다 . 첫 번째 예의 경우 두 번째 미만이 소요될 수 있고 효과가 없기 때문에 최적화 프로그램에 의해 코드가 제거 가능성이 될 수 있습니다.
논의에서 언급했듯이 시간은 OS가 출력을 버퍼링하는 방법, 터미널 에뮬레이터로 출력하는지 여부에 따라 크게 달라 지 몇 분보다 훨씬 수 있습니다.
int로 선언되기 때문에 최대 값에 도달하면 x 값이 음수가되어 루프가 중단됩니다.
그러나 System.out.println이 루프에 추가 실행 속도가 표시됩니다 (콘솔에 출력하면 실행 속도가 느려짐). 그러나 두 번째 프로그램 (루프 내부에 시스템이있는 프로그램)이 충분히 오래 실행 가능하면 첫 번째 프로그램 (루프 내부에 시스템이없는 프로그램)과 동일한 동작을 가져옵니다.
여기에는 두 가지 이유가 있습니다.
Java는
for
루프를 최적화하고 루프x
후를 사용하지 않기 때문에 루프를 제거하기 만하면됩니다.System.out.println(x);
루프 가방 문 을 넣어이를 확인할 수 있습니다 .Java가 실제로 루프를 최적화하지 않고 프로그램을 실행하고 결국
x
너무 커져서int
오버플로가 보관 수 있습니다. 정수 오버플로는 대부분의 경우 정수x
를 j보다 작은 음수로 만들어 루프에서 나와 값을 인쇄합니다y
.System.out.println(x);
루프 내 추가하여 확인할 수도 있습니다 .
또한 첫 번째 경우에도 결국 오버플로가 발생하여 두 번째 경우에도 마찬가지입니다.
둘 다 무한 루프가 실행, 처음에는 j = 0, j <x, j 증가 (j ++) 및 j는 정수 루프가 최대 값에 도달 할 때까지 실행 된 다음 오버플로 (An Integer Overflow가 조건입니다 ) 곱하기 또는 더하기와 같은 산술 연산의 결과가이를 저장하는 데 사용 된 정수 유형의 최대 크기를 초과 할 때 발생합니다.) 두 번째 예의 경우 시스템은 루프가 중단 될 때 y 값을 인쇄합니다.
무한 루프의 예를 보유하고있는 다음과 같이 보일 것입니다.
int x = 6;
for (int i = 0; x < 10; i++) {
System.out.println("Still Looping");
}
(x)는 고유 한 10의 값을 얻지 못하기 때문입니다.
이중 루프로 무한 루프를 만들 수도 있습니다.
int i ;
for (i = 0; i <= 10; i++) {
for (i = 0; i <= 5; i++){
System.out.println("Repeat");
}
}
첫 번째 for 루프가 i <10이라고 말하고 두 번째 for 루프로 들어가고 두 번째 for 루프가 == 5가 될 때까지 (i) 값을 증가시키기 때문에이 루프는 무한합니다. 그런 다음 첫 번째 for 루프로 진행합니다. i <10이기 때문에 for 루프 다시, 두 번째 for 루프 후에 재설정되기 때문에 프로세스가 계속 반복됩니다.
한 번 x
초과 하는 값 2,147,483,647
(의 최대 값 int
) x
은 j
y를 인쇄하든 인쇄하지 않든 음수가되고 더 이상 크지 않기 때문에 유한 루프 입니다.
y
to 의 값을 변경하고 루프에서 100000
인쇄 y
하면 루프가 곧 중단됩니다.
그것이 무한 해 졌다고 느끼는 이유는 System.out.println(y);
아무 동작도하지 않는 것보다 코드가 매우 느리게 실행되도록 만들었 기 때문입니다.
흥미로운 문제 사실 두 경우 모두 루프는 끝이 없습니다
그러나 그들 사이의 주요 차이점은 언제 종료되고 x
최대 int
값 을 초과 하는 데 걸리는 시간 은 2,147,483,647
오버플로 상태에 도달하고 루프가 종료되는 것입니다.
이 문제를 이해하는 가장 좋은 방법은 간단한 예제를 테스트하고 그 결과를 보존하는 것입니다.
예 :
for(int i = 10; i > 0; i++) {}
System.out.println("finished!");
산출:
finished!
BUILD SUCCESSFUL (total time: 0 seconds)
이 무한 루프를 테스트 한 후 종료하는 데 1 초도 걸리지 않습니다.
for(int i = 10; i > 0; i++) {
System.out.println("infinite: " + i);
}
System.out.println("finished!");
산출:
infinite: 314572809
infinite: 314572810
infinite: 314572811
.
.
.
infinite: 2147483644
infinite: 2147483645
infinite: 2147483646
infinite: 2147483647
finished!
BUILD SUCCESSFUL (total time: 486 minutes 25 seconds)
이 테스트 케이스에서 프로그램 실행을 종료하고 완료하는 데 걸리는 시간에 큰 차이가 있음을 알 수 있습니다.
인내하지 않으면이 루프가 끝이없고 종료되지 않을 것이라고 생각할 수 있지만 실제로 종료하고 i
값이 있는 오버플로 상태에 도달하는 데 몇 시간이 걸립니다 .
마지막으로 우리는 print 문을 for 루프 안에 넣은 후에 print 문이없는 첫 번째 경우에 루프보다 훨씬 더 많은 시간이 걸릴 것이라는 결론을 내 렸습니다.
프로그램을 실행하는 데 걸리는 시간은 컴퓨터 사양, 특히 처리 능력 (프로세서 용량), 운영 체제 및 프로그램을 컴파일하는 IDE에 따라 다릅니다.
이 사례를 다음에서 테스트합니다.
Lenovo 2.7GHz Intel Core i5
운영체제 : Windows 8.1 64x
IDE : NetBeans 8.2
프로그램을 마치는 데 약 8 시간 (486 분)이 걸립니다.
또한 for 루프의 단계 증가 i = i + 1
가 최대 int 값에 도달하는 데 매우 느린 요소임을 알 수 있습니다.
이 요소를 변경하고 더 짧은 시간에 루프를 테스트하기 위해 단계를 더 빠르게 증가시킬 수 있습니다.
우리가 i = i * 10
그것을 넣고 테스트한다면 :
for(int i = 10; i > 0; i*=10) {
System.out.println("infinite: " + i);
}
System.out.println("finished!");
산출:
infinite: 100000
infinite: 1000000
infinite: 10000000
infinite: 100000000
infinite: 1000000000
infinite: 1410065408
infinite: 1215752192
finished!
BUILD SUCCESSFUL (total time: 0 seconds)
보시다시피 이전 루프에 비해 매우 빠릅니다.
프로그램 실행을 종료하고 완료하는 데 1 초도 걸리지 않습니다.
이 테스트 예제 이후 나는 문제를 명확히하고 Zbynek Vyskovsky-kvr000의 답변의 타당성을 증명해야한다고 생각하며 , 또한이 질문에 대한 답변이 될 것 입니다.
'IT' 카테고리의 다른 글
서비스에서 UI 프로그램 처리기에 액세스 (0) | 2020.09.11 |
---|---|
버튼 클릭시 체계적으로 양식을 출시하기 위해 Angular2를 피하십시오. (0) | 2020.09.11 |
Vim에서 변수 이름 변경 (0) | 2020.09.11 |
Chrome의 개발자 도구에는없는 Firebug의 기능은 무엇입니까? (0) | 2020.09.11 |
C # 네임 스페이스-요점은 무엇입니까? (0) | 2020.09.11 |