😮문제상황

 

public void calculateFuelTank(List<Checklist> checklists,Yata yata){
        int positiveCount = (int) checklists.stream().filter(Checklist::isCheckpn).count();
        int negativeCount = checklists.size() - positiveCount;
        if(positiveCount>negativeCount) yata.getMember().setFuelTank(yata.getMember().getFuelTank() + 0.1);
        else yata.getMember().setFuelTank(yata.getMember().getFuelTank() - 0.1);
    }
}

프로젝트로 카풀 서비스를 만들던 중

카풀 후 상대에게 리뷰를 작성할 수 있는데

리뷰에서 긍정 체크리스트 항목을 더 많이 체크한 경우 해당 멤버의 매너점수를 0.1씩 올리고,

그렇지 않은 경우 0.1씩 내리는 메서드를 만들고 싶었다

 

그러나

 

요런 식으로 리뷰 점수가 0.1 씩 올라가는게 아니라

0.10000000002 이런식으로 올라가는 것이다

 

 

 

 

 

 

🔎원인

컴퓨터는 모든 숫자를 0과 1로만 표현할 수 있기에 소수를 0과 1로 표현하는 과정에서 오차가 나는 것이다

 

각종 프로그래밍 언어에서는 소수를 표현할 때 IEEE 754 부동 소수점 방식으로 소수를 표현하게 되는데,

java에서도 이 방식으로 소수를 계산한다.

 

자바의 부동 소수점 계산방식에 대한 자세한 내용은 아래 포스팅에 올려놓았다

 

https://develoyummer.tistory.com/66

 

java- IEEE 754 부동 소수점 방식

자바에서 소수의 계산시에 값이 3.02 + 1.06 = 4.08 이렇게 정확하게 떨어지지 않고 3.0800003 이런식으로 나오는 경우가 있다. 이는 자바의 소수점 계산방식 때문이다. 각종 프로그래밍 언어에서는 소

develoyummer.tistory.com

 

 

고정 소수점 방식 정확, 범위가 좁다
부동 소수점 방식 정확도가 떨어짐(근사치 제공) , 범위가 넓다.

 

 🔎BigDecimal

 

따라서 Java에서 정확한 소수 계산을 하고 싶다면
소수점을 정확하계 계산할 수 있게 해주는 라이브러리인 BigDecimal을 사용해주면 된다.

 

 

 

📌선언 및 초기화

BigDecimal num = new BigDecimal("value"); //value는 숫자가 아닌 문자 타입으로 넣어줘야 한다

 

 

📌BigDecimal 을 이용한 사칙연산

더하기 num1.add(num2);
빼기 num1.subtract(num2));
곱하기 num1.multiply(num2));
나누기 num1.divide(num2));

 

 

 

 

✔해결방법

 

따라서 다음과 같이 변환해 주었다

public void calculateFuelTank(List<Checklist> checklists, Yata yata) {
    int positiveCount = (int) checklists.stream().filter(Checklist::isCheckpn).count();
    int negativeCount = checklists.size() - positiveCount;

    BigDecimal ChangeNum = new BigDecimal(String.valueOf(0.1));
    BigDecimal FuelTankScore = new BigDecimal(String.valueOf(yata.getMember().getFuelTank()));

    if (positiveCount > negativeCount) yata.getMember().setFuelTank(FuelTankScore.add(ChangeNum).doubleValue());
    else yata.getMember().setFuelTank(FuelTankScore.subtract(ChangeNum).doubleValue());
}

 

 

이제 정상적으로 잘 올라간다

 

 

 

참고한 자료

https://wakestand.tistory.com/202

 

 

 

복사했습니다!