자바(JAVA) 기초 함께 알아보자

자바(JAVA) 기초 같이 알아보자(4) - 연산 오차

jay_the_code 2024. 9. 18. 22:32

지난번 자바(java)의 연산(operation)에 이어서 이번글에서는 연산과정에서

일어날 수 있는 오차에 대해서 알아보도록 하겠습니다.

 

아래에서 설명할 내용들은 코딩을 시작하는 과정에서부터 인지하고

코드를 작성하는 습관을 들여야 합니다.

 

추후에 연산이 들어간 코드를 짜야하는 상황에서 최대한 오차가 없는 코드를

작성하는 방법입니다.

 

먼저 아래 코드를 보고 어떤 답이 나올지 생각해 보시길 바랍니다.

double a = 0.1
double b = 1.1

if((a+b) == 1.2){
	System.out.println("True");
}else{
	System.out.println("False");
    System.out.println(a + b);
}

 

VScode에 복사해서 직접 console에 나온 답을 확인해 보시는 걸 추천드립니다.  

.

.

.

.

.

.

.

.

.

이제 함께 답을 찾아보도록 하겠습니다.

 

평소대로 계산한다면 a + b = 0.1 + 1.1이므로 1.2 가 나오게 되고

그렇다면 위 코드를 실행하였을 때 True 가 Console에 출력되어야 합니다.

 

하지만 위 코드를 실행해 보면 Console에는 False 가 출력되는 것을 알 수 있습니다.

또한 a + b의 값도 아래와 같이 나오게 됩니다.

 

흥미롭게도 정확하게 1.2가 아닌 다른 소수가 출력되는 것을 확인할 수 있습니다.

 

이제 그 이유에 대해서 알아보도록 하겠습니다.

 

컴퓨터에서 메모리에 데이터를 저장할 때는 이진법을 사용합니다.

따라서 화면에서 1.1, 1.7, 4.8 이런 식으로 소수로 보이는 수들도 

실제 컴퓨터에는 이진수로 변환되어 저장되어 있습니다..

 

이 과정에서 이진수로 깔끔하게 안 떨어지고 소수점이 무한하게 발생하는 수들이

존재하게 되는데 위의 0.1이 그 예시중 하나입니다.

 

0.1을 이진수로 바꾸면 0.000110011001100110011001100.....

위와 같이 무한히 반복되는 패턴을 보입니다.

 

이럴 경우에 컴퓨터는 데이터 타입에 따라 저장할 수 있는 만큼만 저장하고

나머지 수는 버리게 됩니다.

 

따라서 double a = 0.1; 을 보면 실제로 a 에는 0.1이 아닌 0.1에 가까운 수

저장됩니다.

 

이런 식으로 근사치로 계산된 수들이 많아지고 연산하는 과정에서

또다시 근사치로 계산되는 과정들이 반복될 수 있습니다.

결과적으로 코드에서 유의미한 오차가 발생할 수 있고 그렇게 되면

의도와는 다른 결과를 야기할 수 있습니다.

 

이런 문제점들을 예방하기 위한 몇 가지 방법들을 소개해드리겠습니다.

 

  1. 정수로 계산
    ex) 2.6cm라는 값을 저장하고 싶다면 26mm로 변환해서 넣기

  2. 반올림 문법
    반올림 문법을 사용하여 끝에 0.0000000002를 남겨두지 않고 잘라내고
    계산하는 코드를 작성하는 방법이 있습니다.

  3. float 사용을 자제하고 double을 사용
    이 방법 역시 오차가 발생할 수 있지만 float보다 double이 더 많은 데이터를
    저장할 수 있는 데이터 타입이기 때문에 오차가 작게 발생합니다.
    하지만 double은 float보다 두 배의 메모리 공간을 차지한다는 점에 유의해야 합니다.

 

지금까지 소수에 관련하여 발생할 수 있는 오차에 대해서 알아보았습니다.

각자 코드 상황에 맞게 올바른 방법을 적용하여 오차 없는 수식을 작성하시길 바랍니다!

 

다음에는 자바의 비교연산자(comparison operator)와 논리 연산자(logical operator)

에 대해서 알아보겠습니다.