1️⃣ 정수형
정수형 데이터 타입 종류
Java에서 정수를 저장할 수 있는 기본 타입(primitive type)에는 byte, short, ing, long이 있다.
각 타입은 저장 크기와 표현 가능한 값의 범위가 다르며, 메모리 효율과 성능을 고려하여 선택해야 한다.
데이터 타입 | 크기 (비트) | 저장 가능한 값의 범위 | 기본 값 (초기화 시) | 사용 예 |
byte | 8비트 | -128 ~ 127 | 0 | 메모리 절약이 중요한 경우, 파일 I/O, 네트워크 데이터 처리 |
short | 16비트 | -32,768 ~ 32,767 | 0 | 메모리 절약이 필요한 경우 (ex. 대량의 데이터 처리) |
int | 32비트 | -2,147,483,648 ~ 2,147,483,647 | 0 | 기본적인 정수 연산 (일반적인 숫자 연산) |
long | 64비트 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | 0L | 큰 정수를 다룰 때 (ex. 금융, 빅데이터) |
정수형 변수 선언
byte a = 127; // byte 타입 (최대값 127)
short b = 32000; // short 타입
int c = 100000; // int 타입 (기본 정수 타입)
long d = 10000000000L; // long 타입 (L을 붙여야 함)
System.out.println(a); // 127
System.out.println(b); // 32000
System.out.println(c); // 100000
System.out.println(d); // 10000000000
- long 타입을 사용할 때는 L(대문자) 또는 l(소문자)을 접미사로 붙여야 함
- 기본 정수형은 int이므로, long 리터럴을 명시적으로 사용해야 함
정수형 산술 연산 (int)
int a = 13;
int b = 4;
System.out.println(a + b); // 더하기 / 17
System.out.println(a - b); // 빼기 / 9
System.out.println(a * b); // 곱하기 / 52
System.out.println(a / b); // 나누기 (소수점 버림) / 3
System.out.println(a % b); // 모듈러 연산 (소수점 버림) / 1
정수형 비교 연산 (int)
System.out.println(a == b);
System.out.println(a != b);
System.out.println(a > b);
System.out.println(a < b);
System.out.println(a >= b);
System.out.println(a <= b);
오버플로우와 언더플로우
Java에서는 정수 연산을 수행할 때, 연산 과정에서 오버플로우(overflow) 또는 언더플로우(underflow)가 발생할 수 있다.
int max = Integer.MAX_VALUE; // 2,147,483,647 (int의 최댓값)
System.out.println("최댓값: " + max);
int overflow = max + 1; // 오버플로우 발생
System.out.println("오버플로우된 값: " + overflow); // -2,147,483,648 (최솟값으로 돌아감)
int min = Integer.MIN_VALUE; // -2,147,483,648 (int의 최솟값)
int underflow = min - 1; // 언더플로우 발생
System.out.println("언더플로우된 값: " + underflow); // 2,147,483,647 (최댓값으로 돌아감)
- 정수형 타입은 최대값을 초과하면 최솟값으로 돌아감 (오버플로우)
- 최솟값보다 작아지면 최댓값으로 돌아감 (언더플로우)
long을 사용한 큰 숫자 연산
int의 범위를 초과하는 숫자는 long을 사용해야 한다.
long population = 8_000_000_000L; // long 타입 사용 (int 범위를 초과)
System.out.println("세계 인구: " + population);
- 큰 숫자(int 범위 초과)를 다룰 때는 long 타입과 L 접미사를 사용해야 함
- 숫자 가독성을 높이기 위해 _ (언더스코어) 사용 가능 (8_000_000_000L)
BigInteger를 활용한 초대형 숫자 연산
만약 long 조차도 표현할 수 없는 초대형 정수를 다뤄야 한다면, BigInteger 클래스를 사용해야 한다.
import java.math.BigInteger;
public class BigIntegerExample {
public static void main(String[] args) {
BigInteger bigNum1 = new BigInteger("9223372036854775808"); // long 최대값 초과
BigInteger bigNum2 = new BigInteger("10000000000000000000");
BigInteger sum = bigNum1.add(bigNum2);
System.out.println("큰 숫자의 합: " + sum);
}
}
- 초대형 정수(long 초과)를 다룰 때 BigInteger 사용
- 연산(+, -, *, /)은 add(), substract(), multipty(), divide() 메서드로 수행해야 함.
정수형 타입 변환 (형 변환)
Java에서는 더 작은 타입에서 더 큰 타입으로 변환(자동 형 변환, widening)이 가능하지만,
더 큰 타입에서 더 작은 타입으로 변환할 때는 데이터 손실 가능성이 있어 명시적 변환(강제 형 변환, narrowing)이 필요하다.
📌 자동 형 변환 (작은 → 큰)
int num = 100;
long bigNum = num; // int → long 자동 변환
System.out.println(bigNum); // 100 (문제 없음)
- 작은 정수 타입 → 큰 정수 타입 변환은 자동으로 가능
📌 강제 형 변환 (큰 → 작은)
long bigNum = 10000000000L;
int num = (int) bigNum; // 강제 형 변환 (데이터 손실 가능)
System.out.println(num); // 예상치 못한 값이 출력될 가능성 있음
- 큰 정수 타입 → 작은 정수 타입 변환은 (int) bigNum 처럼 명시적 변환 필요
- 데이터 손실 가능성이 있음 (오버플로우 발생 가능)
정수형 리터럴 표기법
Java에서는 정수를 여러 가지 표기법으로 표현할 수 있다.
표기법 | 예제 | 설명 |
10진수 | int a = 123; | 일반적인 정수 |
2진수 | int b = 0b1010; | 0b (또는 0B) 접두사를 사용 |
8진수 | int c = 0123; | 0 접두사를 사용 |
16진수 | int d = 0x1A3F; | 0x (또는 0X) 접두사를 사용 |
📌 예제
public class IntegerLiterals {
public static void main(String[] args) {
int decimal = 123; // 10진수
int binary = 0b1010; // 2진수
int octal = 0123; // 8진수
int hex = 0x1A3F; // 16진수
System.out.println(decimal); // 123
System.out.println(binary); // 10
System.out.println(octal); // 83
System.out.println(hex); // 6719
}
}
2️⃣ 부동소수형
부동소수형 데이터 타입 종류
Java에서 부동소수형 데이터를 표현하는 기본 타입(primitive type)은 float과 double이 있다.
이 두 가지 타입은 IEEE 754 표준 부동소주점 표현 방식을 따르고, 소수점이 있는 실수값을 저장하는 데 사용된다.
데이터 타입 | 크기 (비트) | 저장 가능한 값의 범위 | 소수점 이하 정밀도 | 기본 값 |
float | 32비트 | 약 ±3.4E-38 ~ ±3.4E+38 | 약 7자리 | 0.0f |
double | 64비트 | 약 ±1.7E-308 ~ ±1.7E+308 | 약 15~16자리 | 0.0d |
- 실수 연산을 할 때는 double을 기본적으로 사용하는 것이 권장됨
부동소수형 변수 선언
double d1 = 3.1415926535; // 기본적인 double 선언
double d2 = 1.5e3; // 지수 표기법 사용 (1.5 × 10^3 = 1500.0)
double d3 = -2.7E-4; // 지수 표기법 사용 (-2.7 × 10^-4 = -0.00027)
System.out.println(d1); // 3.1415926535
System.out.println(d2); // 1500.0
System.out.println(d3); // -0.00027
float f1 = 3.1415926535f; // `float`은 `f`(또는 `F`)를 붙여야 함
float f2 = 1.5e3f; // 지수 표기법 사용 (1.5 × 10^3 = 1500.0)
System.out.println(f1); // 3.1415927 (정밀도 한계로 인해 반올림됨)
System.out.println(f2); // 1500.0
부동소수형 연산
double a = 0.1;
double b = 0.2;
double sum = a + b;
System.out.println("0.1 + 0.2 = " + sum); // 예상: 0.3, 실제: 0.30000000000000004
- 부동소수형 연산에서는 근사값 오차가 발생할 수 있음
부동소수형 연산 오류를 방지하는 방법
1. 엡실론(Epsilon) 사용
- 부동소수점 연산 후 정확한 값 비교가 아니라 “거의 같은지”를 비교해야 함
- Math.abs(a - b) < epsilon 형태로 비교
📌 엡실론(Epsilon)이란?
- 엡실론(ε, Epsilon)은 부동소수점 오차를 보정하는 기준값
- 연산 결과가 정확히 일치하는지 비교할 수 없으므로 허용 오차 범위를 설정하는 개념
- Java에서 자주 사용되는 엡실론 값:
- float의 경우: 1e-6 (0.000001)
- double의 경우: 1e-9 (0.000000001)
📌 부동소수점 비교 시 문제점
double a = 0.1 + 0.2;
double b = 0.3;
System.out.println(a == b); // false
- 0.1 + 0.2는 실제로 0.30000000000000004가 됨
- 따라서 a == b 비교는 false가 됨
📌 엡실론을 사용한 비교 방법
double epsilon = 1e-9; // 허용 오차
if (Math.abs(a - b) < epsilon) {
System.out.println("a와 b는 사실상 같다!");
} else {
System.out.println("a와 b는 다르다!");
}
- Math.abs(a - b) < epsilon으로 비교하면 부동소수점 오차를 무시하고 비교 가능
2. BigDecimal 사용 (정확한 소수 연산)
- BigDecimal을 사용하면 부동소수점 오차 없이 정확한 실수 연산 가능
- 단, double을 직접 BigDecimal로 변환하면 오차가 유지되므로 문자열(String)로 변환해야 함.
📌 예제
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal sum = a.add(b); // 0.1 + 0.2
System.out.println(sum.equals(new BigDecimal("0.3"))); // true
double c = 0.1 + 0.2;
System.out.println(sum.equals(BigDecimal.valueOf(c))); // false (double을 직접 BigDecimal로 변환하면 오차가 유지되므로 꼭 문자열로 변환해서 계산하여 사용해야 함)
}
}
- BigDecimal을 사용하면 부동소수점 연산 오류 없이 정확한 결과를 없을 수 있음
- 금융 계산 등 정밀한 연산이 필요한 경우 BigDecimal을 사용하는 것이 필수
📌 BigDecimal의 비교 연산 (equals와 compareTo)
- BigDecimal은 정확한 소수 연산을 위한 클래스이지만, 비교 연산 시 주의할 점이 많다.
- 특히, equals()와 compareTo()의 차이를 이해하는 것이 중요하다.
1. equals()와 compareTo()의 차이점
메서드 | 비교 기준 | 결과 값 | 사용 목적 |
equals() | 값 + 스케일 (소수점 자리수까지 비교) | true or false | 완전히 같은 값인지 확인 |
compareTo() | 값만 비교 (스케일 무시) | -1, 0, 1 | 크기 비교 (정렬, 조건문 사용 가능) |
2. equals() 사용 시 주의할 점
- equals()는 스케일(소수점 자리수)까지 포함하여 비교하기 때문에, 값이 같아도 스케일이 다르면 false를 반환할 수 있다.
import java.math.BigDecimal;
public class BigDecimalEqualsExample {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.0");
BigDecimal b = new BigDecimal("10.00");
System.out.println(a.equals(b)); // false (스케일이 다름)
}
}
- 10.0 과 10.00은 같은 숫자지만, equals()로 비교하면 false
- equals()는 스케일까지 동일해야 같은 값으로 판단
⚒️ 해결 방법 → stripTrailingZeros() 사용
System.out.println(a.stripTrailingZeros().equals(b.stripTrailingZeros())); // true
- stripTrailingZeros()를 사용하면 불필요한 0을 제거하여 비교 가능
3. compareTo() 사용법과 특징
- compareTo()는 값만 비교하고, 스케일은 무시하기 때문에, 10.0 과 10.00을 비교해도 같다고 판단한다.
import java.math.BigDecimal;
public class BigDecimalCompareToExample {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.0");
BigDecimal b = new BigDecimal("10.00");
System.out.println(a.compareTo(b)); // 0 (같은 값으로 판단)
}
}
- compareTo()는 크기 비교할 때 적절한 방법
- 값만 비교하고 소수점 자리수는 무시
✔️ compareTo()의 반환값
- -1 → 왼쪽 값이 작은
- 0 → 두 값이 같음
- 1 → 왼쪽 값이 큼
BigDecimal x = new BigDecimal("5.5");
BigDecimal y = new BigDecimal("10.0");
System.out.println(x.compareTo(y)); // -1 (x < y)
System.out.println(y.compareTo(x)); // 1 (y > x)
System.out.println(y.compareTo(new BigDecimal("10.00"))); // 0 (같은 값)
4. equals() vs compareTo() 언제 사용해야 할까?
상황 | equals() | compareTo() |
완전히 같은 값인지 확인할 때 (소수점 자리수 포함) | 사용 가능 | 부적절 |
단순히 숫자가 같은지 확인할 때 | 부적절 | 사용 가능 |
숫자의 크기를 비교할 때 | 부적절 | 사용 가능 |
정렬이 필요한 경우(TreeSet, TreeMap 등에서 사용) | 부적절 | 사용 가능 |
- 크기 비교 → compareTo()
- 완전히 같은 값인지 확인 → equals()
5. 실무에서 자주 쓰이는 BigDecimal 비교 패턴
- 숫자가 같은지 확인 (소수점 자리수 무시)
if (a.compareTo(b) == 0) {
System.out.println("값이 같습니다.");
}
- 특정 값보다 큰지 확인
if (a.compareTo(new BigDecimal("100.0")) > 0) {
System.out.println("100보다 큽니다.");
}
- 특정 값보다 작은지 확인
if (a.compareTo(new BigDecimal("50.0")) < 0) {
System.out.println("50보다 작습니다.");
}