본문 바로가기

Java의 정석 : 3rd Edition

[Java의 정석 - 연습문제] Chapter03. 연산자(Operator)

Java의 정석 : 3rd Edition, 2016을 개인 학습용으로 정리한 내용입니다.
"ppt 파일 자료, 연습문제"를 학습 용도로 배포할 수 있음을 고지하셨습니다.
저자님께 감사드립니다.

 

 

 

 

[3-1] 다음 연산의 결과를 적으시오.

class Exercise3_1 {
	public static void main(String[] args) {
		int x = 2;
		int y = 5;
		char c = 'A'; // 'A'의 문자코드는 65

		System.out.println(1 + x << 33);               // 1번
		System.out.println(y >= 5 || x < 0 && x > 2);  // 2번
		System.out.println(y += 10 - x++);             // 3번
		System.out.println(x+=2);                      // 4번
		System.out.println( !('A' <= c && c <='Z') );  // 5번
		System.out.println('C'-c);                     // 6번
		System.out.println('5'-'0');                   // 7번
		System.out.println(c+1);                       // 8번
		System.out.println(++c);                       // 9번
		System.out.println(c++);                       // 10번
		System.out.println(c);                         // 11번
	}
}

1번 : 6      // 3 << 33(33 - 32 = 1)
2번 : true    // true || false && false
3번 : 13    // 15(y += 10) - 2(x++ : 후위)
4번 : 4(오답)  5 // 이전의 식(y += 10 - x++)에서 1증가하였으므로 3 += 2 : 5
5번 : false   // !(true && true)
6번 : 2      // 'C'(67) - 'A'(65) : int보다 작은 타입은 int로 변환후 연산
7번 : 5      // '5'(53) - '0'(48) : int보다 작은 타입은 int로 변환후 연산
8번 : 66    // 'A'(65) + 1       : int보다 작은 타입은 int로 변환후 연산
9번 : 'B'    // 단항 연산자 ++ : 형변환 X
10번 : 'B'    // c++ : 후위형은 출력된 후 증가되므로 'B' 
11번 : 'C'    // 후위형(증가) 반영된 문자 'C' 

 

단항 연산자에서 형변환이 발생하지 않는 이유
- 이항 연산자 : 연산을 위해 '피연산자 스택(operand stack)'을 사용하는데 이 과정에서 형변환 발생.
- 단항 연산자(증가연산자('++')) : '피연산자 스택'을 사용하지 않으므로 형변환 발생하지 않음.
println 메서드가 문자 또는 숫자의 출력을 결정하는 기준
값의 타입에 따라 어떻게 출력할지를 결정함.
- 문자타입 : 저장된 값(문자코드)에 해당하는 문자를 출력.
- 숫자 : 숫자로 출력.

 

 

 

 

[3-2] 아래의 코드는 사과를 담는데 필요한 바구니(버켓)의 수를 구하는 코드이다.

만일 사과의 수가 123개이고 하나의 바구니에는 10개의 사과를 담을 수 있다면,

13개의 바구니가 필요할 것이다. (1)에 알맞은 코드를 넣으시오.

class Exercise3_2 {
	public static void main(String[] args) {
		int numOfApples = 123;           // 사과의 개수
		int sizeOfBucket = 10;           // 바구니의 크기(바구니에 담을 수 있는 사과의 개수)
		int numOfBucket = ( /* (1) */ ); // 모든 사과를 담는데 필요한 바구니의 수
        
		System.out.println("필요한 바구니의 수 :"+numOfBucket);
	}
}

 

나의 답 : numOfApples/sizeOfBucket + 1

문제를 있는 그대로 해석. 123개를 10으로 남았을 때 몫이 12가 되므로 1을 더함.

 

해설 : numOfApples/sizeOfBucket + (numOfApples%sizeOfBucket > 0 ? 1 : 0)

사과의 개수(numOfApples)를 바구니의 크기(sizeOfBucket)으로 나눴을 때,

나머지가 있으면 하나의 바구니가 더 필요함.

나머지가 발생하는지 확인하여 나머지가 발생하면 바구니의 개수(numOfBucket)에 1을 더함.

 

 

 

 

[3-3] 아래는 변수 num의 값에 따라 ‘양수’, ‘음수’, ‘0’을 출력하는 코드이다.

삼항 연산자를 이용해서 (1)에 알맞은 코드를 넣으시오.

[Hint] 삼항 연산자를 두 번 사용하라.

class Exercise3_3 {
	public static void main(String[] args) {
		int num = 10;
		System.out.println( /* (1) */ );
	}
}
// 실행결과 : 양수

 

나의 답 : num == 0 ? "0" : (num > 0 ? "양수" : "음수")

 

해설 : num > 0 ? "양수" : (num < 0 ? "음수" : "0")

삼항연산자를 사용하면 2가지 경우의 수를 처리할 수 있다.

삼항연산자에 삼항연산자를 포함시키면 3가지 경우의 수를 처리할 수 있다.

 

 

 

 

[3-4] 아래는 변수 num의 값 중에서 백의 자리 이하를 버리는 코드이다.

만일 변수 num의 값이 '456'이라면 '400'이 되고, '111'이라면 '100'이 된다.

(1)에 알맞은 코드를 넣으시오.

class Exercise3_4 {
	public static void main(String[] args) {
		int num = 456;
		System.out.println( /* (1) */ );
	}
}
// 실행결과 : 400

 

나의 답 : num/100*100       int 타입에서 나눗셈 연산자는 반올림 하지 않고 버리는 성질을 이용

 

 

 

 

[3-5] 아래는 변수 num의 값 중에서 일의 자리를 1로 바꾸는 코드이다.

만일 변수 num의 값이 333이라면 331이 되고, 777이라면 771이 된다. (1)에 알맞은 코드를 넣으시오.

class Exercise3_5 {
	public static void main(String[] args) {
		int num = 333;
		System.out.println( /* (1) */ );
	}
}
// 실행결과 : 331

 

나의 답 : 16진수의 값을 & 연산자로 각 자리의 수를 뽑아내는 예제를 활용하려 했음.

               이 방법이 아닌 것 같아 다른 방법을 생각해봤지만 떠오르지 않았음.

 

해설 : num/10*10+1      왜 이렇게 풀어 볼 생각을 못했을까?

 

 

 

 

[3-6] 변수 num의 값보다 크면서도 가장 가까운 10의 배수에서 변수 num의 값을 뺀 나머지를 구하는 코드이다.

예를 들어, 24의 크면서도 가장 가까운 10의 배수는 30이다. 19의 경우 20이고, 81의 경우 90이 된다.

30에서 24를 뺀 나머지는 6이기 때문에 변수 num의 값이 24라면 6을 결과로 얻어야 한다.

(1)에 알맞은 코드를 넣으시오.

[Hint] 나머지 연산자를 사용하라.

class Exercise3_6 {
	public static void main(String[] args) {
		int num = 24;
		System.out.println( /* (1) */ );
	}
}
// 실행결과 : 6

 

나의 답 : ((10 - (num % 10)) + num - num

① 먼저, 나머지 연산자로 10을 나눴다. (연산결과 : 4)

② 연산결과(4)에 10을 빼려고 했으나, 음수가 되므로 10을 앞에 배치. (연산결과 : 6)

③ 연산결과(6)에 num(24)을 더한 후(30) 다시 num(24)을 뺀다. (연산결과 : 6)

 

해설 : (num/10+1)*10 - num

몫에 1을 더한 후 10을 곱하는 방법.. (감탄..)

 

 

 

 

[3-7] 아래는 화씨(Fahrenheit)를 섭씨(Celcius)로 변환하는 코드이다.
변환공식이 'C = 5/9 × (F - 32)'라고 할 때, (1)에 알맞은 코드를 넣으시오. 
단, 변환 결과값은 소수점 셋째자리에서 반올림해야한다. (Math.round()를 사용하지 않고 처리할 것)

class Exercise3_7 {
	public static void main(String[] args) {
		int fahrenheit = 100;
		float celcius = ( /* (1) */ );
		System.out.println("Fahrenheit:"+fahrenheit);
		System.out.println("Celcius:"+celcius);
	}
}
// 실행결과
// Fahrenheit:100
// Celcius:37.78

 

나의 답 : (5/9 * (fahrenheit - 32)) * 100 + 0.5 / 100f

손 계산으로만 문제를 풀었더니 오답이었다. (문제를 풀면 실행도 해보자)

 

해설 : (int) ((5/9f * (fahrenheit - 32)) * 100 + 0.5) / 100f

5/9의 결과는 0. 두 피연산자 중 한 쪽을 float나 double(5/9f)로 해야만 실수형태의 결과를 얻을 수 있음.

 

① ((5/9f * (fahrenheit - 32)) * 100)

37.77778 * 100 → 3777.778

((5/9f * (fahrenheit - 32)) * 100 + 0.5)

3777.778 + 0.5  3778.278

③ (int) ((5/9f * (fahrenheit - 32))*100 + 0.5)

(int)3778.278   → 3778

(int) ((5/9f * (fahrenheit - 32)) * 100 + 0.5) / 100f

3778 / 100f      → 37.78

 

 

 

 

[3-8] 아래 코드의 문제점을 수정해서 실행결과와 같은 결과를 얻도록 하시오.

class Exercise3_8 {
	public static void main(String[] args) {
		byte a = 10;
		byte b = 20;
		byte c = a + b;
        
		char ch = 'A';
		ch = ch + 2;
        
		float f = 3 / 2;
		long l = 3000 * 3000 * 3000;
        
		float f2 = 0.1f;
		double d = 0.1;
        
		boolean result = d==f2;
        
		System.out.println("c="+c);
		System.out.println("ch="+ch);
		System.out.println("f="+f);
		System.out.println("l="+l);
		System.out.println("result="+result);
	}
}
// 실행결과
// c=30
// ch=C
// f=1.5
// l=27000000000
// result=true

 

나의 답 : 

byte c = a + b;                        →  byte c = (byte) a + b;

ch = ch + 2;                            →  ch = (char)(ch + 2);

float f = 3 / 2;                          →  float f = 3 / 2f;

long l = 3000 * 3000 * 3000;  →  long l = 3000 * 3000 * 3000L;

boolean result = d==f2;          →  boolean result = (float)d==f2;

 

char 타입은 int 타입보다 작은 타입. 덧셈연산 시 int 타입으로 변환되므로 형변환 필요.

println에서 char 타입은 문자로 출력되므로 형변환 필요 없는 줄 알고 헷갈렸다.

 

 

 

 

[3-9] 문자형 변수 ch가 영문자(대문자 또는 소문자)이거나 숫자일 때만 변수 b의 값이 true가 되도록 하는 코드이다.

(1)에 알맞은 코드를 넣으시오.

class Exercise3_9 {
	public static void main(String[] args) {
		char ch = 'z';
		boolean b = ( /* (1) */ );
		System.out.println(b);
	}
}
// 실행결과 : true

 

나의 답 : (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')

비교대상을 양옆에 배치해야 가독성이 좋구나.

 

해설 : ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9')

 

 

 

 

[3-10] 다음은 대문자를 소문자로 변경하는 코드인데, 문자 ch에 저장된 문자가 대문자인 경우에만 소문자로 변경한다.

문자코드는 소문자가 대문자보다 32만큼 더 크다.

예를들어 'A'의 코드는 65이고 'a'의 코드는 97이다. (1)~(2)에 알맞은 코드를 넣으시오.

class Exercise3_10 {
    public static void main(String[] args) {
		char ch = 'A';
		char lowerCase = ( /* (1) */ ) ? ( /* (2) */ ) : ch;
        
		System.out.println("ch:"+ch);
		System.out.println("ch to lowerCase:"+lowerCase);
	}
}
// 실행결과
// ch:A
// ch to lowerCase:a

 

나의 답 : 

(1) ch >= 'A' && ch <= 'Z'       비교대상 앞뒤로 배치.

(2) ch + 32

 

해설 :

(1) ('A' <= ch && ch <= 'Z')

(2) (char)(ch+32)

char 타입은 int 타입보다 작은 타입. 덧셈연산 시 int 타입으로 변환되므로 형변환 필요.

println에서 char 타입은 문자로 출력되므로 형변환 필요 없는 줄 알고 헷갈렸다.