과학

자바로 프로그래밍에 입문할래요: 1.3. 조건문과 반복문 (2)

요새 너무 바빠서 오랜만에 올리네. 조건문과 반복문 마지막이야.

예제 프로그램들을 한 번 음미해보는 시간을 가졌으면 좋겠다. 수학적 지식이 조금 필요할 수는 있겠는데, 어쩔 수 없어. 수학적 능력이 프로그래밍의 천장을 바꾼다고 생각해.

 

1.3. 조건문과 반복문 (1)

1.2. 내장 자료형 (2)

1.2. 내장 자료형 (1)

0.0. 여는 글, 1.1. 첫 프로그램 만들기

 

=================

 

유한합(Finite sum) 계산 프로그램

  <PowersOfTwo>에서 사용된 계산 기법은 여러분이 자주 쓰게 될 것입니다. 두 개의 변수를 사용해서, 하나는 반복문을 컨트롤하고 하나는 계산 결과를 쌓아가는 것입니다. <프로그램 1.3.5, Harmonic>은 같은 기법을 사용해 유한합 HN = 1 + 1/2 + 1/3 + ... + 1/N 을 계산합니다.

 

프로그램 1.3.5: Harmonic numbers

 
public class Harmonic 
{
    public static void main(String[] args) 
    {	// Compute the Nth Harmonic number.
	int N = Integer.parseInt(args[0]);
	double sum = 0.0;
	for (int i = 1; i <= N; i++) 
	{ // Add the ith term to the sum
	    sum += 1.0 / i;
	}
	System.out.println(sum);
    }
}
% java Harmonic 2
1.5
% java Harmonic 10
2.9289682539682538
% java Harmonic 10000
9.898706036044348

 

 

프로그램 1.3.6: Newton's Method

 
public class Sqrt
{
	public static void main(String[] args)
	{
		double c = Double.parseDouble(args[0]);
		double epsilon = 1e-15;
		double t = c;
		while (Math.abs(t - c / t) > epsilon * t)
		{	// Replace t by the average of t and c/t.
			t = (c / t + t) / 2.0;
		}
		System.out.println(t);
	}
}
% java Sqrt 2.0
1.414213562373095
% java Sqrt 2544545
1595.1630010754388

 

  <프로그램 1.3.6>은 뉴턴-랩슨 방법으로도 유명한 제곱근의 계산입니다. 이 원리에 대해서는 간단히만 설명할 것이므로, 궁금하다면 직접 찾아보시는 것을 권합니다. 이는 미분 가능한 함수에서의 근사값을 구하는 방법으로, 이 프로그램에서 사용한 수식은 다음과 같습니다.

 

 

 

프로그램 1.3.7: Converting to binary

 
public class Binary
{
	public static void main(String[] args)
	{ // Print binary representation of N.
		int N = Integer.parseInt(args[0]);
		int v = 1;
		while (v <= N / 2)
			v = 2 * v;
		// Now v is the largest power of 2 <= N.
		
		int n = N;
		while (v > 0)
		{ // Cast out powers of 2 in decreasing order.
			if (n < v)
				System.out.print(0);
			else
			{
				System.out.print(1);
				n -= v;
			}
			v = v / 2;
		}
		System.out.println();
	}
}
% java Binary 19
10011
% java Binary 100000000
101111101011110000100000000

 

  <프로그램 1.3.7>은 십진수의 수를 이진수의 수로 변환해주는 프로그램입니다. 이진수의 가장 큰 자릿수부터, 각 자릿수가 1인지 0인지 판단합니다. 예를 들어 19라면, 각각 16, 8, 4, 2, 1을 비교해가면서 큰지 작은지를 판단해 각 자릿수가 1인지 0인지 판단합니다. 따라서, 19 = 10011(2)이라는 결과를 출력합니다. 다음 그림을 참고해보세요.

 

 

 

 

프로그램 1.3.8: Gambler's ruin simulation

 
public class Gambler
{
	public static void main(String[] args)
	{	// Run T experiments that start with $stake
		// and terminate on 0$ or $goal.
		int stake = Integer.parseInt(args[0]);
		int goal = Integer.parseInt(args[1]);
		int T = Integer.parseInt(args[2]);
		int bets = 0;
		int wins = 0;
		for (int t = 0; t < T; t++)
		{ // Run one experiment.
			int cash = stake;
			while (cash > 0 && cash < goal)
			{ // Simulate one bet.
				bets++;
				if (Math.random() < 0.5)
					cash++;
				else
					cash--;
			} // Cash is either 0 (ruin) or $goal (win)
			if (cash == goal)
				wins++;
		}
		System.out.println(100 * wins / T + "% wins");
		System.out.println("Avg # bets: " + bets / T);
	}
}
% java Gambler 10 20 1000
50% wins
Avg # bets: 100
% java Gambler 50 250 100
19% wins
Avg # bets: 11050
% java Gambler 500 2500 100
21% wins
Avg # bets: 998071

 

  <프로그램 1.3.8>은 여지껏 우리가 작성했던 프로그램들과는 성격이 조금 다릅니다. 이 프로그램은 현실에서 일어날 수 있는 일들을 시뮬레이션하여 우리의 결정을 도와주는 프로그램입니다. 다양한 예제들이 있겠지만, '도박꾼의 파산'으로 유명한 상황을 예제로 보여드리겠습니다.

 

  딜러와의 게임을 해서 1달러를 얻거나, 혹은 잃을 수 있습니다. 승률이 50%인 공평한 도박이라 하더라도, 이를 무한하게 반복하면 어떻게 될까요? 아마 언젠가 도박꾼은 반드시 돈을 전부 잃고 파산하게 될 것입니다. 무한하게 반복하다보면 자기가 가진 돈만큼 연속으로 패배할 날이 올테니까요.

 

  하지만 도박꾼이 목표 자금을 정해놓고, 그 목표 자금을 달성했을 때 뒤도 돌아보지 않고 그 자리를 떠날 수 있다면 어떨까요? 도박꾼이 딜러와의 게임에서 승리자가 될 가능성은 얼마일까요?

 

 

  프로그램은 초기자본과 목표, 시도횟수를 인자로 받게됩니다. 초기자본으로 시작해서, 딜러와의 게임에서 계속 승리해 목표자금에 달성하거나, 혹은 많은 패배를 하여 자금을 전부 탕진할 때까지 계속하게 됩니다. 이를 시도횟수만큼 반복하여, 돈을 탕진하지 않고 몇 번이나 목표한 자금까지 달성했는지를 알려줍니다.

 

 

프로그램 1.3.9: Factoring integers

 
public class Factors
{
	public static void main(String[] args)
	{
		// Print the prime factors of N.
		long N = Long.parseLong(args[0]);
		long n = N;
		for (long i = 2; i <= n / i; i++)
		{ // Test whether i is a factor.
			while (n % i == 0)
			{ // Cast out and print i factors,
				n /= i;
				System.out.print(i + " ");
			} // Any factors of n are greater than i.
		}
		if (n > 1)
			System.out.print(n);
		System.out.println();
	}
}
% java Factors 3757208
2 2 2 7 13 13 397

 

  <프로그램 1.3.9>는 양의 정수를 소인수분해하는 프로그램입니다. 우리는 이 프로그램을 통해 컴퓨터의 위력을 체감할 수 있습니다. 10억정도의 숫자도 1초 안에 소인수분해를 마칠 수 있습니다. 반복문은 우리에게 어려운 문제들을 해결할 수 있게 해줍니다.

 

 

조건문과 반복문의 다른 구성들

  다음 기술할 것들은 여러분이 자주 사용하진 않을 것이지만, 꼭 알아두어야 할 구문들입니다.

 

 

break문

  가끔은 반복문의 중간에서 그 즉시 반복문을 탈출하고 싶을 때가 있습니다. 자바에선 break문으로 이런 문제를 해결할 수 있습니다. 다음 코드 조각은 1보다 큰 정수가 소수인지 아닌지를 효과적으로 판별합니다.

 

 
int i;
for (i = 2; i <= N / i; i++)
	if (N % i == 0) break;
if (i > N / i)
	System.out.println(N + " is prime");

 

  이 코드에서 for 반복문을 탈출하는 방법은 두 가지입니다: (N % i == 0)이 참이어서 break문을 통해 탈출하거나, for문의 종료로 탈출하는 것입니다. 전자의 경우 N이 i로 나누어 떨어졌으므로, 소수가 아닙니다. 

 

  여기서 유의해야 할 사항은, 만약 for문 내부에서 i를 선언했다면, i의 범위는 for문 내부이므로 바깥 if문에서 사용될 수 없다는 사실입니다. 

 

 
for (int i = 2; i <= N / i; i++)
	if (N % i == 0) break;
if (i > N / i) // Compile error, the variable i is undefined.
	System.out.println(N + " is prime");

 

 

continue문

  반복문에서 이하 구문들을 전부 실행하고 다음 반복으로 넘어가는 것이 아닌, 중간에 나머지 시퀀스를 건너 뛰고 바로 다음 반복으로 넘어가는 것도 있습니다. 바로 continue문입니다. 반복문 바디에서 continue 가 실행되었을 때, 제어 흐름은 그 즉시 증감문(increment statement)으로 넘어가며 다음 루프를 순회하게 됩니다.

 

 

switch문

  if와 if-else문은 제어 흐름의 방향을 하나 혹은 두 개정도로만 선택할 수 있습니다. 하지만 가끔은 작업이 두 개 이상의 상호독립적인 선택에 놓일 때도 있습니다. 우리는 이전에 if-else문을 엮어서 사용하는 방법을 배웠었지만, switch문을 이용한 해결책도 있습니다.

  변수 day의 값이 0부터 6사이의 값에 따라 각기 다른 요일을 출력하게 되는 코드 조각입니다.

 

 
switch (day)
{
case 0: System.out.println("Sun"); break;
case 1: System.out.prinltn("Mon"); break;
case 2: System.out.prinltn("Tue"); break;
case 3: System.out.prinltn("Wed"); break;
case 4: System.out.prinltn("Thu"); break;
case 5: System.out.prinltn("Fri"); break;
case 6: System.out.prinltn("Sat"); break;
}

 

 

do-while문

 
do { <statements> } while { <boolean expression>);

 

  이 템플릿은 사실 우리가 배운 while문과 별반 다르지 않습니다.

 

 
while (<boolean expression>) { <statements> }

 

  단 하나만 제외하면 말이죠. 처음에는 조건 확인을 하지 않는다는 것입니다. 즉 먼저 실행(do)하고, 반복(while)합니다. 가끔은 이런 do-while문이 유용한데, 예를 들어 좌표 평면 위에 무작위 점을 생성하는 문제를 생각해보죠. 이 점은 2*2 사각형 안에 있어야 하지만, 그 사각형을 내접하는 원 바깥쪽에 있어야 합니다. 이 점의 x좌표와 y좌표를 무작위로 생성하는 프로그램입니다.

 

 
do
{ // Scale x and y to be random in (-1, 1).
x = 2.0*Math.random() - 1.0;
y = 2.0*Math.random() - 1.0;
} while (Math.sqrt(x*x + y*y) > 1.0);

 

  이를 가장 간단하게 해결하는 방법은, 우선 2*2 사각형 안에 점을 무작위로 생성하고 그 좌표가 내접원 안에 있는지 검증하는 것입니다. 만약 아니라면, 다시 무작위 생성 및 검증을 반복하는 것이죠.

 

  처음 반복문을 시작할 때, x와 y의 값이 정해지지도 않았는데 조건식에 대입해볼 수는 없죠. 따라서 do-while문을 통해 x와 y의 값을 먼저 정하고, 반복을 시작합니다.

 

 

무한 반복문(Infinite loops)

  반복문을 작성하기 전에는, 다음 문제에 대해 필히 생각해보셔야 합니다: 반복문의 조건이 항상 만족된다면?

 

  <BadHellos>는 이런 무한 반복문의 예시를 보여줍니다. 요즘에야 터미널 윈도우에 글자를 표시하는 것으로 print를 사용하므로, 그 결과를 OS의 능력 내에서 무한하게 보여줄 수 있습니다. 하지만 만약 print의 행위가 종이에 글자를 인쇄하는 것이었다면 어떨까요? 여러분은 종이를 다 써버리거나, 프린터의 전원을 서둘러 꺼야 했을 것입니다. 

 

 
public class BadHellos
{
	public static void main(String[] args)
	{
		System.out.println("1st Hello");
		System.out.println("2nd Hello");
		System.out.println("3rd Hello");
		int i = 4;
		while (i > 3)
		{
			System.out.println(i + "th Hello");
			i++;
		}
	}
}
% java BadHellos
1st Hello
2nd Hello
3rd Hello
4th Hello
5th Hello
6th Hello
...

 

  Eclipse에서는 터미널의 빨간 초록색 사각형 버튼을 누르면 해당 프로그램을 정지할 수 있습니다. 대부분의 터미널 환경에선 Ctrl-C 혹은 Ctrl-Z 를 이용해 정지할 수 있습니다.

 

  둘째로, 아무런 일이 일어나지 않을 수도 있습니다. 여러분의 프로그램이 무한 반복문에 갇혀서 탈출하지 못하고 그 안에서 아무런 출력도 하지 않는다면, 이건 마치 프로그램이 아무것도 하지 않는 것처럼 보입니다. 이런 일은 가끔 일어나므로, 여러분들은 반복문의 구성을 신중히 해야할 것입니다. 버그를 찾아내는 쉬운 방법 중 하나는, System.out.println()과 같은 것을 이용해 값을 추적해보는 것입니다.

 

  이런 의도치 않은 무한 반복문은 심각한 문제를 초래할 수도 있으므로, 언제나 신중하게 작성해야 합니다.

 

 

 

  조건문과 반복문을 배우는데에는 왕도가 없습니다. 여러분들은 반드시 프로그램을 직접 작성해보고, 실행해보아야 합니다.  그 어떤 프로그래머들도 첫 술에 배부르려고 하지 않습니다. 곧 여러분들도 프로그램이 무엇이고 어떤 것을 하는 것인지에 대해 차근차근 이해할 날이 올 것입니다. 

 

  다음 챕터에서 우리는, 기존에 다뤄보았던 데이터들보다 훨씬 더 많은 데이터들을 정의하고 처리해볼 것입니다.

 

1.3. 조건문과 반복문 끝.

21개의 댓글

2021.04.06

쪼금 아쉬운 건 답이 바로 나와있는 거?

약간 긁어야만 볼 수 있다던가 하면 좋을 거 같아

생각할 시간도 없이 답부터 보니까 재미가 떨어짐 ㅠ

0
2021.04.07
@숨은음은

아마 초보자는 답을 봐도 모르겠을 거야..ㅎㅎ 입문자에게 양보를

0
2021.04.06

구글 승소 기념 댓글

0
2021.04.06

좋은 글 개추

0

자바추

0
DPs
2021.04.07

요즘 자바 공부하면서 느끼는게 이 언어는 대체 뭐에 써먹는 언어임??

비하가 아니라 용도를 진짜로 하나도 못찾겠음

성능보면 더 로우레벨로 가는게 맞고, 웹같은 가벼운 서비스면 js가 콜드스타트 속도가 넘사고..

자바는 무거워서 콜드스타트 제일 높다보니 요즘 웹 인프라에 최악이고, 진짜 무거운 머신러닝쪽은 더 로우레벨 언어로 가잖아

대체 어디에 써야하는 언어인거야?

0
2021.04.07
@DPs

안드로이드만 해도 자바로 짬;

안드로이드 스튜디오 메인 언어가 자바 또는 코틀린임

0
DPs
2021.04.07
@숨은음은

자바 저작권으로 막힌지가 언젠데

유지보수야 하겠지만 신규개발 당연히 코틀린으로 함;

그리고 내가 말하는건 메리트임

빠르던가 성능이 좋거나 뭔가 있어야 할거아냐

그걸 알려달라는거지

어디에 적합한지

0
2021.04.07
@DPs

이번에 공익사용으로 자바 사용 금지 해제되서 또 어찌될 지 모르겠다.

실제로 막힌게 아니라 OpenJDK로 변환 걸어서 잘만 사용하고 있음

안드 게임 어플 만드는데 다 OpenJDK 씀

0
DPs
2021.04.07
@숨은음은

근데 플랫폼은 굳이 자바를?

내가 대표라면 무조건 향후 라이센스 문제 없는 코틀린 할듯

듣기로는 코틀린이 속도도 나쁘지 않다고 들어서 안드개발 코틀린이 낫지 않나 생각하고

애초에 요즘 RN으로 어플 개발 다 넘어가는 추세잖아

안드도 자바 점유율 떨어지는중이고, RN때매 조만간 사라질 급이던데

누가 인건비가 반값! 외치는데 안가냐고 ㅋㅋ

0
2021.04.07
@DPs

아니 유니티 등 각종 엔진들은 기본 JDK 변환을 아직 하고 있고

애드몹 등 구글 서비스는 아직도 자바 또는 코틀린으로 문서 표시 다 되있어;

코틀린으로 변환되겠지만(당연히 구글이 불안한 자바 때려치고 코틀린을 만든가니까)

그렇다고 아직 태생이 자바인 안드 전체에 JDK가 남아있으니 별 수 있간..

아직까지는 이라는 거지 앞으로도라고 말한 거 아님

1
DPs
2021.04.07
@숨은음은

ㅇㅎ 현재야 뭐 자바공화국 한국에 안드도 자바 많은거 맞지

그래서 자바 배우곤 있는데 신규 서비스 구축 면에서 진짜 메리트가 너무 안보여서 궁금했음

0
2021.04.07
@DPs

나는 c맨이라 자바 몰라 ㅋㅋ 근데

그래서 안드 스튜디오 내에서 처리해야하는 구문들은 걍 회사차원에서 포기해가지고

자바 안해도 되서 다행이야..

0
2021.04.07
@DPs

우선 서버 프로그램이나 안드로이드에는 자바를 사용하고 있지. 다만 점유율이 줄어들고 있다는 사실은 맞는 것 같아. 학부생인지라 자세히는 잘 모르겠네. 사실 나도 궁금해 이런 현실적인 문제들.

그래도 자바는 완벽히 객체지향을 구현하는 언어 중에 하나잖아. 현재 우리나라는 여전히 자바를 많이 쓰고 있고, 공부하기 아주 좋은 언어지. 자바를 다루고 자바를 쓰는 프로그램의 소스들을 봤을 때, 나는 개인적으로 객체지향에 대한 시야가 굉장히 넓어지는 느낌을 받았어.

0
DPs
2021.04.07
@스비니

객체지향 자체가 한물 가고있는 실리콘밸리의 유일한 결점이라 불릴정도의 구조라서

자바조차 함수형 JAVA8인가 부터 지원하고, 방향 자체가 FP로 가는 걸로 알고 있음

점유율은 과거 높았다는 걸 알고있고, 지금도 낮지 않다는 걸 알지만, 현재는 왜 쓰는 지 아무도 말을 못하는 언어인 것 같아서 너무 궁금했어

1
2021.04.07
@DPs

객체지향이 한물 가고 있고, 함수형 프로그래밍이 대세가 될 것이라는 이야기에 대한 객관적인 근거나 자료들을 볼 수 있을까? 나도 읽어보고 싶어서.

함수형 프로그래밍을 이전에 한 번 접해본 적이 있었는데, 내가 이전까지 했던 프로그래밍에 대한 사고를 완전히 뒤엎어야 돼서 재밌다고 생각했거든. 흥미가 가서 언젠가는 한 번 공부해볼 생각인데, 함수형 프로그래밍을 바라보는 시각들도 좀 알고 싶네.

1
DPs
2021.04.07
@스비니

전에 본 자료 못찾겠어서 검색해서 볼만한 키워드들 알려주자면

pure function, react 원칙, fp, monad 같은거 찾아봐봐

원래 함수형 프로그래밍이 50년대인가 훨씬 더 옛날에 나왔다가 러닝커브때문에 묻히고, 다시 주목받는 걸로 알고있어

1
2021.04.08

아직 열심히 쓰고있군 ㅊㅊ

0
2021.04.10

방탈ㅈㅅ 님 키배학개론3 언제나옴? 기다르는중

0
28 일 전
@Aussie

코런 건 없어용

0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜
493 [과학] 자바로 프로그래밍에 입문할래요: 1.5. 입출력 (1) 1 스비니 1 4 일 전
492 [과학] 자바로 프로그래밍에 입문할래요: 1.4. 배열 (3) 1 스비니 4 13 일 전
491 [과학] 일론 머스크는 스티브 잡스 같은 사람이다. (feat. 뉴럴링크) 38 빨머 20 14 일 전
490 [과학] 자바로 프로그래밍에 입문할래요: 1.4. 배열 (2) 9 스비니 2 20 일 전
489 [과학] 방사선에 관하여_20210423_Ch.4까지 완료 63 ptrtype01 4 21 일 전
488 [과학] 日 자민당 의원이 공개한 원전오염수 성분 31 SOLEUS 16 23 일 전
487 [과학] ??? : 한국이 오염수 더 많이 방류한다 빼애액 24 SOLEUS 13 23 일 전
486 [과학] 일본의 방사능 기준치가 신용받지 못하는 이유 71 뭘까요 1 24 일 전
485 [과학] 도쿄의 암 발생률. 27 뭘까요 5 24 일 전
484 [과학] 일본은 과연 후쿠시마 인근만 방사능에 오염돼었을까? 13 뭘까요 10 24 일 전
483 [과학] 일본이 주장하는 후쿠시마의 방사능량은 서울과 같다는게 사... 31 뭘까요 14 24 일 전
482 [과학] 일본 후쿠시마 오염수 방류 팩트정리 21 뭘까요 7 24 일 전
481 [과학] 자바로 프로그래밍에 입문할래요: 1.4. 배열 (1) 13 스비니 7 28 일 전
480 [과학] 약사가 쓴 az백신과 혈전에 관한 글 109 pipo 40 2021.04.08
479 [과학] 자바로 프로그래밍에 입문할래요: 1.3. 조건문과 반복문 (2) 21 스비니 4 2021.04.06
478 [과학] 사회과학계에서 밝혀졌던 "보이루"의 실체 13 안티파굳 23 2021.04.05
477 [과학] 피임약은 어떻게 임신을 예방할까? 33 동식 18 2021.04.01
476 [과학] 자바로 프로그래밍에 입문할래요: 1.3. 조건문과 반복문 (1) 11 스비니 2 2021.03.27
475 [과학] 급성 방사선 장해의 치료 역사, 그리고 방법은 무엇일까? 20 바른말고운말하는사람 7 2021.03.24
474 [과학] 자바로 프로그래밍에 입문할래요: 1.2. 내장 자료형 (2) 23 스비니 5 2021.03.23