1. 실수
가장 간단한 계산기나 숫자 계산이 필요한 프로그램을 만든다고 가정해 봅시다(돈 계산부터 복잡한 물리 연산까지). 현실 세계의 값이 항상 정수인 것은 아닙니다 — 어쩔 수 없죠!
그러니 새로운 데이터 타입으로 무장해 봅시다!
프로그래밍에서 실수는 흔히 실수 또는 부동소수점 수(floating-point)라고도 부릅니다. Java를 포함한 대부분의 언어에서 실수 타입은 정수뿐 아니라 “소수” 값(예: 3.14, -28.57, 2.718281828 등)을 저장하는 데 사용됩니다.
부동소수점 수에는 두 가지 기본 타입이 있습니다:
| 타입 | 저장 대상 | 값 범위(대략) | 정밀도 | 일반적인 크기 |
|---|---|---|---|---|
|
숫자 | ±1.5 × 10-45 ... ±3.4 × 1038 | ~소수점 이하 약 7자리 | 4바이트 |
|
숫자 | ±5.0 × 10-324 ... ±1.7 × 10308 | ~소수점 이하 약 15–16자리 | 8바이트 |
타입 float
float는 floating-point number에서 온 이름으로, “부동소수점 수”를 뜻합니다. 실수는 수학적인 개념이고, 컴퓨터에는 다양한 제약이 있습니다. 그래서 Java에서 실수를 “실수(real number)”라고 부르는 것은 완전히 정확하지 않습니다. 일반적으로 “부동소수점 수”라는 이름을 사용합니다.
float는 보통 7개의 유효 숫자(예: 0.1234567)와 10의 지수를 저장하며 메모리에서 4바이트를 차지합니다. 정밀 계산에는 매우 부족하기 때문에 대부분은 빠르게 배정밀도 타입으로 넘어가게 됩니다.
타입 double
double은 배정밀도(double precision)에서 이름이 왔습니다. 메모리에서 8바이트를 차지하며(float의 2배) 최대 15개의 유효 숫자를 저장할 수 있습니다: 0.123456789012345. 대부분의 실수 연산에는 충분한 정밀도를 제공하므로, Java에서 실수를 저장할 때 기본적으로 사용하는 타입이 double입니다.
이번 강의에서는 double에 초점을 맞춥니다. 일반적인 실수에는 기본적으로 double을 권장합니다. 이후에 float도 살펴보겠습니다.
2. double 타입 변수 선언과 초기화
int와 기본은 같습니다 — 이제 double을 사용합니다.
// 변수를 선언하고 원주율(π) 값을 할당
double pi = 3.1415926;
// 초기화 없이 선언만 할 수도 있음
double averageSalary;
averageSalary = 91234.56;
// 계산도 가능!
double pizzaPieces = 8;
double friends = 3;
double piecesPerFriend = pizzaPieces / friends; // 2.666... (2가 아님)
문법상의 특징:
- 10진 소수 구분자로는 점(3.14)을 사용합니다. 쉼표를 쓰면 컴파일 오류가 납니다!
- 엄밀히 말해 double d = 3;처럼 써도 오류가 나지 않습니다 — 형이 자동으로 변환됩니다(정수가 손실 없이 “부동소수점”으로 바뀝니다).
3. Scanner로 실수 입력과 출력
먼저 실수를 출력해 봅시다:
double amount = 42.75;
System.out.println(amount); // 출력: 42.75
잘 작동합니다! 문자열을 합치면 어떨까요:
System.out.println("계좌 잔액: " + amount + " 유로."); // 계좌 잔액: 42.75 유로.
키보드 입력
double을 입력하려면 Scanner의 전용 메서드 console.nextDouble()을 사용합니다.
Scanner console = new Scanner(System.in);
System.out.println("바깥 기온을 입력하세요:");
double temperature = console.nextDouble(); // 바로 double로 입력
System.out.println("현재 야외 기온: " + temperature + " 도.");
4. double 실전: 산술
익숙한 연산자(+, -, *, /)는 int와 동일하게 동작합니다:
double distance = 100.5;
double time = 2.0;
double speed = distance / time; // 50.25
System.out.println("평균 속도: " + speed); // 평균 속도: 50.25
차이점은 하나뿐입니다: 피연산자 중 하나라도 double이면 나눗셈 결과는 항상 실수입니다.
int와 비교
int a = 5, b = 2;
System.out.println(a / b); // 2 (나머지는 버려짐)
double aa = 5, bb = 2;
System.out.println(aa / bb); // 2.5
5. double 사용 시 흔한 오류와 이상한 점
입력 변환 오류
전형적인 상황입니다: 사용자는 3,14를 입력하지만, 프로그램은 3.14를 기대합니다. Java에서 Scanner.nextDouble()은 현재 로케일을 따릅니다. 러시아/독일 로케일에선 쉼표가 허용되지만, 영어 로케일에선 점을 사용해야 합니다. 필요하다면 Scanner의 로케일을 설정하거나 문자열로 읽어 직접 파싱하세요.
// Locale.US 환경에서 "3,14"를 입력하면 문제가 발생함
double value = console.nextDouble();
컴퓨터의 부동소수점 “정밀도” 문제
여기서 초보자들이 종종 당황합니다:
double x = 0.1 + 0.2;
System.out.println(x); // 음... 0.30000000000000004
축하합니다, 컴퓨터 내부에서 실수가 표현되는 방식의 “마법”을 보신 겁니다. 많은 수는 이진수로 정확히 표현할 수 없습니다. 대부분의 애플리케이션에서는 큰 문제가 아니지만, 금융이나 정밀 과학 분야에선 주의가 필요합니다.
6. 중요: double과 int — 자동 변환과 명시적 변환
정수와 실수를 더하거나 int 값을 double 변수에 대입해도 오류는 없습니다:
int i = 2;
double d = i; // 문제 없음!
System.out.println(d); // 2
double dd = 3.7;
int ii = (int) dd; // double을 int로 명시적 캐스팅해야 함!
System.out.println(ii); // 3, 소수 부분이 버려짐
종종 왜 캐스팅 후 소수 부분이 사라지는지 놀라곤 합니다. int 타입은 소수를 저장할 수 없기 때문입니다(점 뒤의 모든 부분은 영구히 사라집니다).
double을 int로 변환하고 (int) 연산자를 사용하는 법은 다음 강의에서 자세히 다룹니다.
7. 서식 지정 출력: 보기 좋게 double 출력하기
기본적으로 double은 불필요한 0이 많이 붙어 출력될 때가 있습니다. 서식을 지정해 출력할 수 있습니다:
double temp = 23.56789;
System.out.println(temp); // 23.56789
// 소수점 이하 2자리
System.out.println(String.format("%.2f", temp)); // 23.57
// 소수점 이하 1자리
System.out.println(String.format("%.1f%n", temp)); // 23.6
| 형식 | 결과 | 설명 |
|---|---|---|
|
23.57 | 소수점 이하 2자리로 출력된 수 |
|
23.6 | 소수점 이하 1자리로 출력된 수 |
8. float와 double 사용 시 흔한 오류
오류 №1: double을 float로 암시적으로 변환
float f = 1.23; // 오류!
컴파일러는 “double을 float에 넣으려 한다 — 정밀도가 손실될 수 있다!”고 경고합니다. 항상 f 접미사를 붙이세요.
오류 №2: int끼리의 나눗셈 결과는 int라는 사실을 잊음
int a = 7, b = 2;
double result = a / b; // 3.0, 3.5가 아님
소수 결과를 얻으려면 적어도 하나의 피연산자를 명시적으로 변환하세요:
double result = (double) a / b; // 3.5
오류 №3: 부동소수점 비교
부동소수점을 ==로 비교하지 마세요. 작은 허용 오차(epsilon)를 사용해 비교하세요.
오류 №4: float의 정밀도 손실
큰 수나 매우 정확한 값을 float에 저장하지 마세요 — 값이 깨지거나 중요한 숫자를 잃을 수 있습니다.
GO TO FULL VERSION