콘텐츠로 이동

2단원 숙제 정답: 변수, 기본형, 진법, 형변환


문제 1. 대입은 오른쪽부터

a=12
b=7
처음:     a=7,  b=12
a=a+b:   a=19, b=12
b=a-b:   a=19, b=7
a=a-b:   a=12, b=7

각 대입문은 오른쪽 계산을 모두 끝낸 뒤 왼쪽 변수에 저장한다. 이 방법은 덧셈 결과가 int 범위를 넘으면 실패할 수 있으므로, 일반적으로는 tmp 변수를 이용한 교환이 더 안전하다.

문제 2. 컴파일러의 관점

항목 결과 이유
컴파일 오류 b + 1의 산술 결과는 int다. intbyte에 자동 대입할 수 없다.
-128 명시적 형변환은 가능하다. 127 다음의 8비트 값은 10000000, 즉 -128이다.
컴파일 오류 final 상수는 한 번 초기화한 뒤 값을 변경할 수 없다.
컴파일 오류 3.14는 접미사가 없으므로 double 리터럴이다. float f = 3.14f;로 써야 한다.

문제 3. 리터럴과 진법

변수 타입 10진수 값
a long 3,000,000,000
b int 51,966
c int 45
d char 65 ('A')
45 / 2d / 55 / A

0b10110132 + 8 + 4 + 1이므로 45다. %x는 소문자 16진수, %o는 8진수, %c는 문자로 출력한다.

문제 4. printf의 폭과 정밀도

[00042]
[Java  ]
[Jav]
[   3.142]

%05d는 폭 5칸을 0으로 채운다. %-6s-는 왼쪽 정렬이고, %.3s는 앞의 3글자만 출력한다. %8.3f는 소수점 아래 3자리로 반올림한 뒤 전체 폭 8칸에 오른쪽 정렬한다.

문제 5. Scanner의 입력 버퍼 함정

name에는 빈 문자열 ""이 저장되므로 출력은 []다. nextInt()는 숫자만 읽고 줄 끝의 개행 문자는 남겨 둔다. 다음 한 줄을 nextInt()nextLine() 사이에 넣는다.

sc.nextLine(); // nextInt() 뒤에 남은 줄바꿈 소비

수정된 핵심 부분은 다음과 같다.

int age = sc.nextInt();
sc.nextLine();
String name = sc.nextLine();

문제 6. 진법 변환과 표현

  1. 0x2F + 0b1010 = 47 + 10 = 57
  2. 57(10) = 111001(2) = 71(8) = 39(16)
  3. 0.1011(2) = 1×2^-1 + 0×2^-2 + 1×2^-3 + 1×2^-4 = 0.5 + 0.125 + 0.0625 = 0.6875

문제 7. 8비트 2의 보수

37은 8비트로 00100101이다.

  00100101  (37)
  11011010  (1의 보수)
+        1
----------
  11011011  (-37)

따라서 16진수로는 0xDB이다. -37 + 37의 계산은 다음과 같다.

  11011011
+ 00100101
----------
1 00000000

8비트 밖으로 나간 자리올림은 버리므로 최종 결과는 00000000, 즉 0이다.

문제 8. char는 문자이면서 정수다

57
10
C
결과 타입 이유
(int)c int 문자 '9'의 유니코드 값은 57
c - '0' + 1 int char의 산술 연산은 int로 승격; 57 - 48 + 1
(char)('A' + 2) char 'A' + 2int이므로 char로 명시적 변환

문제 9. float의 정밀도 손실

f=91234568
back=91234568
false

float는 10진수 약 7자리 정밀도이므로 8자리 정수 91234567을 정확히 저장하지 못하고 가까운 값 91234568으로 바꾼다. 다시 int로 변환해도 이미 잃은 원래의 1자리 정보는 복구되지 않는다.

문제 10. 명시적/자동 형변환

-126
-3
2
2.5

③은 두 피연산자가 int라서 정수 나눗셈을 먼저 수행하고, ④는 2.0double이므로 5double로 자동 형변환된 뒤 실수 나눗셈을 수행한다.

문제 11. 1바이트 진법 리포트

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Decimal (0-255): ");
        int value = sc.nextInt();

        String hex = Integer.toHexString(value);
        String binary = Integer.toBinaryString(value);
        binary = String.format("%8s", binary).replace(' ', '0');

        System.out.printf("decimal : %3d%n", value);
        System.out.printf("hex     : 0x%s%n", hex);
        System.out.printf("binary  : %s%n", binary);
    }
}

String.format("%8s", binary)는 최소 폭 8칸에 오른쪽 정렬한 문자열을 만들고, 앞 공백을 0으로 바꿔 8자리 2진수로 만든다.

문제 12. 입력값의 의미를 지켜라

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Student code: ");
        // 앞의 0도 학생 번호의 일부이므로 수가 아닌 문자열로 보존한다.
        String code = sc.nextLine();

        System.out.printf("Registered: [%s-A]%n", code);
    }
}

int로 읽으면 00721은 수치값 721이 되어 앞의 0 정보가 사라진다. 값이 계산 대상이 아니라 식별 대상이면 String이 적절하다.