[TIL] Java 부동소수점(float, double)과 BigDecimal 정확도 차이 이해하기

2025. 10. 18. 22:56·Programming Language/Java

부동 소수점?

  • 정수 부분과 소수 부분 모두 다 가진 값을 말합니다.
  • 자바에 부동 소숫값을 담는 데이터 유형은 총 두 가지 입니다.
    • double과 float

double

  • 기본적인 부동 소수 리터럴 유형
  • 8바이트
  • 어떤 부동소수 연산이던 결과는 항상 double
double dbl = 34.5678;

float

  • 4바이트
  • 부동 소숫값 뒤에 꼭 f를 붙여함
float f = 34.5; //에러

float f = 34.5f;
float f = 34.5F;

형변환 오류

  • 큰 타입→ 작은 타입으로 변환 할 때 오류가 발생합니다.
  • 위를 예로 들자면 double → float로 변환시 에러가 난다는걸 확인할 수 있습니다
public class main
{
    public static void main(String[] args)
    {
        double dbl = 3.45;
        float f = dbl;
    }
}

//incompatible types: possible lossy conversion from double to float
//      float f = dbl;
                 ^
//1 error
  • 이는 전 글에서 말했던 명시적 형변환으로 간단히 해결할 수 있습니다

부동소수점에 형변환 적용하기

명시적 형변환

  • 큰 타입 → 작은 타입
public class main
{
    public static void main(String[] args)
    {
        double dbl = 3.45;
        float f = (float) dbl;
        System.out.println(f);
    }
}

// 3.45

암묵적 형변환

  • 작은 타입 → 큰 타입
public class main
{
    public static void main(String[] args)
    {
        float f2 = 3.45f;
        double dbl2 = f2;
        System.out.println(dbl2);
    }
}
// 3.450000047683716
  • 여기서 보면 출력값이 이상한걸 확인하실 수 있습니다.
  • 아래에서 자세히 살펴보도록 하겠습니다

부동소수점의 문제점

System.out.println(34.56789876 + 34.2234);
//출력값 : 68.79129875999999
  • 갑자기 9는 어디서 나온걸까요?
💡 대부분의 부동소수 오차는 IEEE 754 표준의 이진 부동소수 표현 방식 때문입니다. 10진수를 2진수로 바꿀 때 일부 소수가 무한 이진소수로 변환되어 정확히 저장되지 못합니다. (참고)
  • 따라서 부동소수는 소숫점값을 명료하게 나타내지 않아서 결과의 정확성이 요구되는 것에는 부동소수 데이터 유형을 계산에서는 float와 double을 사용하지 않는 게 좋습니다
  • 정확한 결과를 원한다면 BigDecimal 클래스를 사용해야합니다

BigDecimal 클래스

  • BigDecimal은 자바 클래스
import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number1 = new BigDecimal("34.56789876");
        BigDecimal number2 = new BigDecimal("34.2234");
        System.out.println(number1.add(number2));
    }
}

//출력값: 68.79129876
  • 여기서 중요한 점은, 자바에서 BigDecimal 클래스는 변경 불가능하다는 점
  • BigDecimal 객체는 불변(Immutable) 클래스입니다. 한 번 생성된 값은 변경할 수 없고, 연산 시 새로운 객체를 반환합니다.

BigDecimal에 문자열을 넣는 이유?

  • 정확성을 올리기 위해서
import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number1 = new BigDecimal(34.56789876);
        BigDecimal number2 = new BigDecimal(34.2234);
        BigDecimal number3 = number1.add(number2);
        System.out.println(number3);
    }
}

///68.79129875999999654823113814927637577056884765625
  • double 타입을 사용해서 만들었더니 출력값이 매우 이상해졌습니다
  • 정확한 것을 원한다면 문자열을 사용!!

BigDecimal 끼리만 연산이 가능해요

import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number = new BigDecimal("11.5");
        BigDecimal number2 = new BigDecimal("23.45678");
        int i = 5;
        System.out.println(number.add(i));
    }
}
  • 이렇게 타입이 다른데 더할 경우 에러가 발생합니다
  • 무조건 BigDecimal 끼리만 연산해주세요
import java.math.BigDecimal;
public class main
{
    public static void main(String[] args)
    {
        BigDecimal number = new BigDecimal("11.5");
        BigDecimal number2 = new BigDecimal("23.45678");
        int i = 5;
        System.out.println(number.add(new BigDecimal(i)));
    }
}

//출력값: 16.5

(BigDecimal 메서드 같은 경우 이 글에서 배우고 있습니다!)


예제 BigDecimal로 이자 계산기 만들기

import java.math.BigDecimal;

public class SimpleInterestCalculator {
    private BigDecimal principal;
    private BigDecimal interest;

    public SimpleInterestCalculator(String principal, String interest) {
        this.principal = new BigDecimal(principal);
        this.interest = new BigDecimal(interest);
    }

    public BigDecimal calculateTotalValue(BigDecimal noOfYears) {
        BigDecimal interestRate = this.interest.divide(new BigDecimal("100"));

        // 2. 총 이자 계산 (원금 * 이율 * 기간)
        // (Principal * Rate * Time)
        BigDecimal totalInterest = this.principal.multiply(interestRate).multiply(noOfYears);

        // 3. 총액 계산 (원금 + 총 이자)
        // (Principal + Total Interest)
        BigDecimal totalValue = this.principal.add(totalInterest);

        // 4. 총액 반환
        return totalValue;
    }

}

import java.math.BigDecimal;
public class SimpleInterestCalculatorRunner
{
    public static void main(String[] args)
    {
        SimpleInterestCalculator calculator = new SimpleInterestCalculator("4500.00", "7.5");
	 
	// '5'는 문자형, 5는 숫자형 → 문자 '5'는 내부적으로 아스키코드 53으로 처리됩니다.
        BigDecimal totalValue = calculator.calculateTotalValue(new BigDecimal("5"));
        System.out.println(totalValue);
    }
}

 


✍️ 요약

Java의 float와 double은 부동소수점 오차를 가질 수 있습니다.

정확한 계산이 필요한 금융, 이자 계산, 금액 처리에서는 BigDecimal 클래스를 사용해야 합니다.

특히 new BigDecimal("문자열") 형태로 선언하면 오차 없이 안전하게 연산할 수 있습니다.


📚 참고자료 

  • ☕ BigInteger & BigDecimal 사용법 정리 – 인파
  • ☕ 실수 표현(부동 소수점)-원리 한눈에 이해하기 – 인파
  • TIL 이전 글 – joon0112
  • Udemy Java Programming (온라인 강좌)

'Programming Language > Java' 카테고리의 다른 글

[WIL] 자바의 객체지향부터 BigDecimal까지 — 실수와 학습의 한 주  (0) 2025.10.20
[TIL] Java 불리안, 문자형, 그리고 정적 메서드 정리  (0) 2025.10.19
[TIL] Java 자료형과 형변환 완전 정리 (Wrapper Class · 진수 체계)  (0) 2025.10.18
[TIL] 자바(Java) 생성자(Constructor) 완벽 정리: 메소드 오버로딩과 함께 사용하는 예제  (0) 2025.10.16
[TIL] Java 객체의 상태와 캡슐화 - Setter, Getter로 배우는 OOP 기본  (0) 2025.10.15
'Programming Language/Java' 카테고리의 다른 글
  • [WIL] 자바의 객체지향부터 BigDecimal까지 — 실수와 학습의 한 주
  • [TIL] Java 불리안, 문자형, 그리고 정적 메서드 정리
  • [TIL] Java 자료형과 형변환 완전 정리 (Wrapper Class · 진수 체계)
  • [TIL] 자바(Java) 생성자(Constructor) 완벽 정리: 메소드 오버로딩과 함께 사용하는 예제
dev_Hyeonjoon
dev_Hyeonjoon
문제를 풀며 사람들에게 감동✨을 전하고 가치를 만드는 개발자가 되고 싶습니다 💻
  • dev_Hyeonjoon
    Hyeonjoon's code
    dev_Hyeonjoon
  • 전체
    오늘
    어제
    • 분류 전체보기 (50)
      • Programming Language (29)
        • JavaScript (0)
        • Java (27)
      • Front-end (10)
        • React-project (5)
        • Vanilla[JS]-project (5)
        • study (0)
      • AI Tools (1)
      • Back-end (0)
      • 독서록 (0)
      • 기타 (5)
      • Trouble Shooting (2)
        • Python (1)
      • 자격증 (1)
      • 알고리즘 (1)
        • 백준 (1)
      • FrameWork (0)
        • Node.js (Express.js) (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    군대에서코딩
    객체지향
    바닐라js
    형변환
    사지방
    토이프로젝트
    파이썬
    자바공부
    조건문
    사지방코딩
    구름IDE
    군자기계발
    Til
    코딩
    자바
    Java
    자바기초
    리액트
    vanillajs
    OOP
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
dev_Hyeonjoon
[TIL] Java 부동소수점(float, double)과 BigDecimal 정확도 차이 이해하기
상단으로

티스토리툴바