임의 정밀도 연산 - 큰 수와 정확한 실수 계산
Java API Reference
import java.math.BigInteger;
public class BigIntegerCreation {
public static void main(String[] args) {
// 문자열로 생성
BigInteger bi1 = new BigInteger("123456789012345678901234567890");
System.out.println("From string: " + bi1);
// long으로 생성
BigInteger bi2 = BigInteger.valueOf(1000000);
System.out.println("From long: " + bi2);
// 진법 지정
BigInteger binary = new BigInteger("1010", 2);
BigInteger hex = new BigInteger("FF", 16);
System.out.println("Binary 1010: " + binary); // 10
System.out.println("Hex FF: " + hex); // 255
// 상수
System.out.println("ZERO: " + BigInteger.ZERO);
System.out.println("ONE: " + BigInteger.ONE);
System.out.println("TWO: " + BigInteger.TWO);
System.out.println("TEN: " + BigInteger.TEN);
// 큰 수 예시
BigInteger factorial100 = factorial(100);
System.out.println("100!: " + factorial100);
}
// 팩토리얼 계산
public static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
}public class BigIntegerArithmetic {
public static void main(String[] args) {
BigInteger a = new BigInteger("100");
BigInteger b = new BigInteger("30");
// 덧셈
BigInteger sum = a.add(b);
System.out.println("100 + 30 = " + sum); // 130
// 뺄셈
BigInteger diff = a.subtract(b);
System.out.println("100 - 30 = " + diff); // 70
// 곱셈
BigInteger product = a.multiply(b);
System.out.println("100 * 30 = " + product); // 3000
// 나눗셈
BigInteger quotient = a.divide(b);
System.out.println("100 / 30 = " + quotient); // 3
// 나머지
BigInteger remainder = a.remainder(b);
System.out.println("100 % 30 = " + remainder); // 10
// 나눗셈과 나머지 동시에
BigInteger[] divRem = a.divideAndRemainder(b);
System.out.println("Quotient: " + divRem[0]); // 3
System.out.println("Remainder: " + divRem[1]); // 10
// 거듭제곱
BigInteger power = a.pow(3);
System.out.println("100³ = " + power); // 1000000
// 절댓값
BigInteger negative = new BigInteger("-100");
BigInteger abs = negative.abs();
System.out.println("abs(-100) = " + abs); // 100
// 부호 반전
BigInteger negated = a.negate();
System.out.println("negate(100) = " + negated); // -100
}
}public class BigIntegerComparison {
public static void main(String[] args) {
BigInteger a = new BigInteger("100");
BigInteger b = new BigInteger("200");
BigInteger c = new BigInteger("100");
// compareTo: 음수, 0, 양수
System.out.println(a.compareTo(b)); // -1 (a < b)
System.out.println(a.compareTo(c)); // 0 (a == c)
System.out.println(b.compareTo(a)); // 1 (b > a)
// equals
System.out.println(a.equals(c)); // true
System.out.println(a.equals(b)); // false
// min, max
BigInteger min = a.min(b);
BigInteger max = a.max(b);
System.out.println("min(100, 200) = " + min); // 100
System.out.println("max(100, 200) = " + max); // 200
}
}public class BigIntegerBitwise {
public static void main(String[] args) {
BigInteger a = new BigInteger("10"); // 1010
BigInteger b = new BigInteger("6"); // 0110
// AND
BigInteger and = a.and(b);
System.out.println("10 & 6 = " + and); // 2 (0010)
// OR
BigInteger or = a.or(b);
System.out.println("10 | 6 = " + or); // 14 (1110)
// XOR
BigInteger xor = a.xor(b);
System.out.println("10 ^ 6 = " + xor); // 12 (1100)
// NOT
BigInteger not = a.not();
System.out.println("~10 = " + not); // -11
// 쉬프트
BigInteger leftShift = a.shiftLeft(2); // 곱하기 4
BigInteger rightShift = a.shiftRight(1); // 나누기 2
System.out.println("10 << 2 = " + leftShift); // 40
System.out.println("10 >> 1 = " + rightShift); // 5
// 비트 조작
BigInteger setBit = a.setBit(0); // 0번 비트를 1로
BigInteger clearBit = a.clearBit(1); // 1번 비트를 0으로
BigInteger flipBit = a.flipBit(0); // 0번 비트 반전
System.out.println("setBit(10, 0) = " + setBit); // 11
System.out.println("clearBit(10, 1) = " + clearBit); // 8
System.out.println("flipBit(10, 0) = " + flipBit); // 11
// 비트 카운트
int bitCount = a.bitCount();
int bitLength = a.bitLength();
System.out.println("bitCount(10) = " + bitCount); // 2 (1의 개수)
System.out.println("bitLength(10) = " + bitLength); // 4 (필요한 비트 수)
}
}public class BigIntegerMath {
public static void main(String[] args) {
// 소수 판별
BigInteger num = new BigInteger("97");
boolean isPrime = num.isProbablePrime(10); // 확률적 소수 판별
System.out.println("97 is prime: " + isPrime); // true
// 다음 소수 찾기
BigInteger nextPrime = num.nextProbablePrime();
System.out.println("Next prime after 97: " + nextPrime); // 101
// 최대공약수 (GCD)
BigInteger a = new BigInteger("48");
BigInteger b = new BigInteger("18");
BigInteger gcd = a.gcd(b);
System.out.println("gcd(48, 18) = " + gcd); // 6
// 모듈러 연산
BigInteger base = new BigInteger("5");
BigInteger exponent = new BigInteger("10");
BigInteger modulus = new BigInteger("13");
BigInteger result = base.modPow(exponent, modulus);
System.out.println("5^10 mod 13 = " + result); // 4
// 모듈러 역원
BigInteger inverse = base.modInverse(modulus);
System.out.println("5^-1 mod 13 = " + inverse); // 8
// 5 * 8 = 40 ≡ 1 (mod 13)
}
}public class BigIntegerConversion {
public static void main(String[] args) {
BigInteger big = new BigInteger("123456789");
// 기본 타입으로 변환
int intValue = big.intValue(); // 오버플로우 가능!
long longValue = big.longValue();
float floatValue = big.floatValue();
double doubleValue = big.doubleValue();
System.out.println("int: " + intValue);
System.out.println("long: " + longValue);
// 정확한 변환 (예외 발생 가능)
try {
int exact = big.intValueExact(); // 범위 초과 시 ArithmeticException
} catch (ArithmeticException e) {
System.out.println("int 범위 초과!");
}
// 문자열 변환
String decimal = big.toString(); // 10진수
String binary = big.toString(2); // 2진수
String hex = big.toString(16); // 16진수
System.out.println("Decimal: " + decimal);
System.out.println("Binary: " + binary);
System.out.println("Hex: " + hex);
// 바이트 배열
byte[] bytes = big.toByteArray();
BigInteger fromBytes = new BigInteger(bytes);
System.out.println("From bytes: " + fromBytes);
}
}import java.math.BigDecimal;
public class BigDecimalCreation {
public static void main(String[] args) {
// ❌ double로 생성 (부정확할 수 있음)
BigDecimal bd1 = new BigDecimal(0.1);
System.out.println("From double: " + bd1);
// 0.1000000000000000055511151231257827021181583404541015625
// ✅ 문자열로 생성 (정확)
BigDecimal bd2 = new BigDecimal("0.1");
System.out.println("From string: " + bd2); // 0.1
// valueOf 사용 (권장)
BigDecimal bd3 = BigDecimal.valueOf(0.1);
System.out.println("valueOf: " + bd3); // 0.1
// 정수로 생성
BigDecimal bd4 = BigDecimal.valueOf(100);
System.out.println("From int: " + bd4); // 100
// 상수
System.out.println("ZERO: " + BigDecimal.ZERO);
System.out.println("ONE: " + BigDecimal.ONE);
System.out.println("TEN: " + BigDecimal.TEN);
}
}import java.math.RoundingMode;
public class BigDecimalArithmetic {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.5");
BigDecimal b = new BigDecimal("3.2");
// 덧셈
BigDecimal sum = a.add(b);
System.out.println("10.5 + 3.2 = " + sum); // 13.7
// 뺄셈
BigDecimal diff = a.subtract(b);
System.out.println("10.5 - 3.2 = " + diff); // 7.3
// 곱셈
BigDecimal product = a.multiply(b);
System.out.println("10.5 * 3.2 = " + product); // 33.60
// 나눗셈 (반올림 모드 필요!)
BigDecimal quotient = a.divide(b, 2, RoundingMode.HALF_UP);
System.out.println("10.5 / 3.2 = " + quotient); // 3.28
// 나눗셈 (무한소수 가능성 있으면 예외)
try {
BigDecimal bd1 = new BigDecimal("1");
BigDecimal bd2 = new BigDecimal("3");
BigDecimal result = bd1.divide(bd2); // ArithmeticException!
} catch (ArithmeticException e) {
System.out.println("무한소수: 반올림 모드 필요!");
}
// 거듭제곱
BigDecimal power = a.pow(2);
System.out.println("10.5² = " + power); // 110.25
// 절댓값
BigDecimal negative = new BigDecimal("-10.5");
BigDecimal abs = negative.abs();
System.out.println("abs(-10.5) = " + abs); // 10.5
}
}public class RoundingModes {
public static void main(String[] args) {
BigDecimal value = new BigDecimal("10.5");
BigDecimal divisor = new BigDecimal("3");
System.out.println("10.5 / 3 =");
// HALF_UP: 반올림 (5 이상 올림)
System.out.println("HALF_UP: " +
value.divide(divisor, 2, RoundingMode.HALF_UP)); // 3.50
// HALF_DOWN: 반내림 (5 이하 내림)
System.out.println("HALF_DOWN: " +
value.divide(divisor, 2, RoundingMode.HALF_DOWN)); // 3.50
// HALF_EVEN: 짝수 쪽으로 (은행가 반올림)
System.out.println("HALF_EVEN: " +
value.divide(divisor, 2, RoundingMode.HALF_EVEN)); // 3.50
// UP: 무조건 올림
System.out.println("UP: " +
value.divide(divisor, 2, RoundingMode.UP)); // 3.50
// DOWN: 무조건 내림
System.out.println("DOWN: " +
value.divide(divisor, 2, RoundingMode.DOWN)); // 3.50
// CEILING: 양의 무한대 방향
System.out.println("CEILING: " +
value.divide(divisor, 2, RoundingMode.CEILING)); // 3.50
// FLOOR: 음의 무한대 방향
System.out.println("FLOOR: " +
value.divide(divisor, 2, RoundingMode.FLOOR)); // 3.50
// 실제 차이가 나는 예시
BigDecimal val = new BigDecimal("2.5");
BigDecimal div = BigDecimal.ONE;
System.out.println("\n2.5 / 1 =");
System.out.println("HALF_UP: " +
val.divide(div, 0, RoundingMode.HALF_UP)); // 3
System.out.println("HALF_DOWN: " +
val.divide(div, 0, RoundingMode.HALF_DOWN)); // 2
System.out.println("HALF_EVEN: " +
val.divide(div, 0, RoundingMode.HALF_EVEN)); // 2 (짝수)
}
}public class BigDecimalComparison {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.50");
BigDecimal b = new BigDecimal("10.5");
// compareTo (값 비교)
System.out.println(a.compareTo(b)); // 0 (값이 같음)
// equals (값과 스케일 모두 비교)
System.out.println(a.equals(b)); // false! (스케일이 다름)
System.out.println("a scale: " + a.scale()); // 2
System.out.println("b scale: " + b.scale()); // 1
// 값 비교는 compareTo 사용!
if (a.compareTo(b) == 0) {
System.out.println("값이 같음");
}
// 정밀도
System.out.println("a precision: " + a.precision()); // 4 (유효숫자)
System.out.println("b precision: " + b.precision()); // 3
// stripTrailingZeros: 후행 0 제거
BigDecimal stripped = a.stripTrailingZeros();
System.out.println("Stripped: " + stripped); // 10.5
System.out.println("Scale: " + stripped.scale()); // 1
}
}public class BigDecimalScale {
public static void main(String[] args) {
BigDecimal value = new BigDecimal("10.123");
// setScale: 소수점 자리 조정
BigDecimal scaled1 = value.setScale(2, RoundingMode.HALF_UP);
System.out.println("Scale to 2: " + scaled1); // 10.12
BigDecimal scaled2 = value.setScale(5, RoundingMode.HALF_UP);
System.out.println("Scale to 5: " + scaled2); // 10.12300
// movePointRight/Left: 소수점 이동
BigDecimal moved1 = value.movePointRight(2); // 곱하기 100
System.out.println("Move right 2: " + moved1); // 1012.3
BigDecimal moved2 = value.movePointLeft(1); // 나누기 10
System.out.println("Move left 1: " + moved2); // 1.0123
// scaleByPowerOfTen: 10의 거듭제곱 곱하기
BigDecimal scaled = value.scaleByPowerOfTen(2);
System.out.println("Scale by 10²: " + scaled); // 1012.3
}
}public class FloatingPointIssue {
public static void main(String[] args) {
// double의 문제
double d1 = 0.1;
double d2 = 0.2;
double sum = d1 + d2;
System.out.println("0.1 + 0.2 = " + sum); // 0.30000000000000004
System.out.println("Is 0.3? " + (sum == 0.3)); // false!
// BigDecimal로 해결
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.2");
BigDecimal bdSum = bd1.add(bd2);
System.out.println("\nBigDecimal:");
System.out.println("0.1 + 0.2 = " + bdSum); // 0.3
System.out.println("Is 0.3? " + (bdSum.compareTo(new BigDecimal("0.3")) == 0)); // true
// 금액 계산 예시
System.out.println("\n=== 금액 계산 ===");
// ❌ double 사용
double price = 0.1;
double quantity = 3;
double total = price * quantity;
System.out.println("double: " + total); // 0.30000000000000004
// ✅ BigDecimal 사용
BigDecimal bdPrice = new BigDecimal("0.1");
BigDecimal bdQuantity = new BigDecimal("3");
BigDecimal bdTotal = bdPrice.multiply(bdQuantity);
System.out.println("BigDecimal: " + bdTotal); // 0.3
}
}import java.math.MathContext;
public class FinancialCalculation {
public static void main(String[] args) {
// 상품 가격 계산
BigDecimal price = new BigDecimal("1234.56");
BigDecimal taxRate = new BigDecimal("0.1"); // 10% 세금
// 세금
BigDecimal tax = price.multiply(taxRate)
.setScale(2, RoundingMode.HALF_UP);
System.out.println("Tax: " + tax); // 123.46
// 총액
BigDecimal total = price.add(tax);
System.out.println("Total: " + total); // 1358.02
// 할인 적용
BigDecimal discount = new BigDecimal("0.2"); // 20% 할인
BigDecimal discountAmount = total.multiply(discount)
.setScale(2, RoundingMode.HALF_UP);
BigDecimal finalPrice = total.subtract(discountAmount);
System.out.println("Discount: " + discountAmount); // 271.60
System.out.println("Final: " + finalPrice); // 1086.42
// 월 이자 계산 (연 5%, 12개월)
BigDecimal principal = new BigDecimal("10000");
BigDecimal annualRate = new BigDecimal("0.05");
BigDecimal months = new BigDecimal("12");
BigDecimal monthlyRate = annualRate.divide(months, 10, RoundingMode.HALF_UP);
BigDecimal interest = principal.multiply(monthlyRate)
.setScale(2, RoundingMode.HALF_UP);
System.out.println("\nMonthly interest: " + interest); // 41.67
}
}public class PerformanceComparison {
public static void main(String[] args) {
int iterations = 1000000;
// int 연산
long start = System.nanoTime();
int sum1 = 0;
for (int i = 0; i < iterations; i++) {
sum1 += i;
}
long end = System.nanoTime();
System.out.println("int time: " + (end - start) / 1000000.0 + "ms");
// BigInteger 연산
start = System.nanoTime();
BigInteger sum2 = BigInteger.ZERO;
for (int i = 0; i < iterations; i++) {
sum2 = sum2.add(BigInteger.valueOf(i));
}
end = System.nanoTime();
System.out.println("BigInteger time: " + (end - start) / 1000000.0 + "ms");
// BigDecimal 연산
start = System.nanoTime();
BigDecimal sum3 = BigDecimal.ZERO;
for (int i = 0; i < iterations; i++) {
sum3 = sum3.add(BigDecimal.valueOf(i));
}
end = System.nanoTime();
System.out.println("BigDecimal time: " + (end - start) / 1000000.0 + "ms");
System.out.println("\n결론: 기본 타입이 훨씬 빠름!");
System.out.println("BigInteger/BigDecimal은 정확성이 필요할 때만 사용");
}
}public class OptimizationTips {
public static void main(String[] args) {
// 1. valueOf 재사용
BigInteger bi1 = BigInteger.valueOf(100); // 캐싱됨
BigInteger bi2 = BigInteger.valueOf(100); // 같은 객체
System.out.println(bi1 == bi2); // true (작은 값은 캐싱)
// 2. 상수 재사용
BigInteger result = BigInteger.ZERO;
for (int i = 0; i < 10; i++) {
result = result.add(BigInteger.ONE); // ONE 재사용
}
// 3. 불필요한 변환 피하기
// ❌ 비효율적
BigDecimal bad = new BigDecimal(Double.toString(0.1));
// ✅ 효율적
BigDecimal good = new BigDecimal("0.1");
// 4. MathContext 활용
MathContext mc = new MathContext(10); // 유효숫자 10자리
BigDecimal bd1 = new BigDecimal("1");
BigDecimal bd2 = new BigDecimal("3");
BigDecimal result2 = bd1.divide(bd2, mc);
System.out.println("1/3: " + result2); // 0.3333333333
// 5. 적절한 타입 선택
// 정수 연산 → BigInteger
// 실수 연산 (정확성 필요) → BigDecimal
// 일반 연산 → 기본 타입 (int, long, double)
}
}// n번째 피보나치 수 계산 (BigInteger)
public class Problem1 {
public static BigInteger fibonacci(int n) {
// 여기에 코드 작성
return null;
}
public static void main(String[] args) {
System.out.println("Fib(100): " + fibonacci(100));
}
}정답:
정답 보기
public class Problem1 {
public static BigInteger fibonacci(int n) {
if (n <= 1) return BigInteger.valueOf(n);
BigInteger a = BigInteger.ZERO;
BigInteger b = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
BigInteger temp = a.add(b);
a = b;
b = temp;
}
return b;
}
// 재귀 + 메모이제이션
static Map<Integer, BigInteger> memo = new HashMap<>();
public static BigInteger fibonacci2(int n) {
if (n <= 1) return BigInteger.valueOf(n);
if (memo.containsKey(n)) {
return memo.get(n);
}
BigInteger result = fibonacci2(n - 1).add(fibonacci2(n - 2));
memo.put(n, result);
return result;
}
}// 원금, 연이율, 기간으로 복리 계산
// 최종 금액 = 원금 * (1 + 이율)^기간
public class Problem2 {
public static BigDecimal compoundInterest(
BigDecimal principal,
BigDecimal rate,
int years) {
// 여기에 코드 작성
return null;
}
public static void main(String[] args) {
BigDecimal principal = new BigDecimal("1000000"); // 100만원
BigDecimal rate = new BigDecimal("0.05"); // 연 5%
int years = 10;
BigDecimal result = compoundInterest(principal, rate, years);
System.out.println("10년 후: " + result);
}
}정답:
정답 보기
public class Problem2 {
public static BigDecimal compoundInterest(
BigDecimal principal,
BigDecimal rate,
int years) {
// (1 + rate)
BigDecimal multiplier = BigDecimal.ONE.add(rate);
// (1 + rate)^years
BigDecimal result = principal;
for (int i = 0; i < years; i++) {
result = result.multiply(multiplier);
}
return result.setScale(2, RoundingMode.HALF_UP);
}
// pow 사용 버전 (정수 지수만 가능)
public static BigDecimal compoundInterest2(
BigDecimal principal,
BigDecimal rate,
int years) {
BigDecimal multiplier = BigDecimal.ONE.add(rate);
// multiplier^years
BigDecimal power = multiplier.pow(years);
return principal.multiply(power)
.setScale(2, RoundingMode.HALF_UP);
}
}// 여러 실수의 정확한 평균 계산
public class Problem3 {
public static BigDecimal average(String... numbers) {
// 여기에 코드 작성
return null;
}
public static void main(String[] args) {
BigDecimal avg = average("0.1", "0.2", "0.3");
System.out.println("Average: " + avg); // 0.2
}
}정답:
정답 보기
public class Problem3 {
public static BigDecimal average(String... numbers) {
if (numbers.length == 0) {
return BigDecimal.ZERO;
}
BigDecimal sum = BigDecimal.ZERO;
for (String num : numbers) {
sum = sum.add(new BigDecimal(num));
}
BigDecimal count = BigDecimal.valueOf(numbers.length);
return sum.divide(count, 10, RoundingMode.HALF_UP);
}
// Stream 사용 버전
public static BigDecimal average2(String... numbers) {
if (numbers.length == 0) {
return BigDecimal.ZERO;
}
BigDecimal sum = Arrays.stream(numbers)
.map(BigDecimal::new)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal count = BigDecimal.valueOf(numbers.length);
return sum.divide(count, 10, RoundingMode.HALF_UP);
}
}// 생성
BigInteger bi = new BigInteger("123456789012345678901234567890");
BigInteger bi2 = BigInteger.valueOf(1000000);
// 연산
bi.add(bi2) // 덧셈
bi.subtract(bi2) // 뺄셈
bi.multiply(bi2) // 곱셈
bi.divide(bi2) // 나눗셈
bi.pow(3) // 거듭제곱
// 비교
bi.compareTo(bi2) // 음수, 0, 양수
bi.equals(bi2) // 같은지
// 유틸리티
bi.gcd(bi2) // 최대공약수
bi.isProbablePrime(10) // 소수 판별// 생성 (문자열 권장!)
BigDecimal bd = new BigDecimal("0.1"); // 정확
BigDecimal bd2 = BigDecimal.valueOf(0.1);
// 연산 (반올림 모드 주의!)
bd.add(bd2)
bd.subtract(bd2)
bd.multiply(bd2)
bd.divide(bd2, 2, RoundingMode.HALF_UP) // 소수점 2자리, 반올림
// 비교 (compareTo 사용!)
bd.compareTo(bd2) == 0 // 값 비교
bd.equals(bd2) // 값과 스케일 모두 비교
// 스케일
bd.setScale(2, RoundingMode.HALF_UP) // 소수점 조정
bd.stripTrailingZeros() // 후행 0 제거RoundingMode.HALF_UP // 반올림 (일반적)
RoundingMode.HALF_DOWN // 반내림
RoundingMode.HALF_EVEN // 은행가 반올림
RoundingMode.UP // 올림
RoundingMode.DOWN // 내림
RoundingMode.CEILING // 양의 무한대 방향
RoundingMode.FLOOR // 음의 무한대 방향// BigInteger: 매우 큰 정수, 정확한 정수 연산
factorial(100), fibonacci(1000), RSA 암호화
// BigDecimal: 정확한 실수 연산
금융 계산, 회계, 과학 계산
// 기본 타입: 일반적인 경우 (성능 중요)
일반 계산, 반복문, 알고리즘| Chapter | 주제 |
|---|---|
| 01. Math 클래스 | 수학 연산, 삼각함수, 난수 |
| 02. Wrapper 클래스 | Integer, Double, Boxing |
| 03. BigInteger & BigDecimal | 큰 수, 정확한 실수 |