brunch

You can make anything
by writing

C.S.Lewis

by 강관우 Dec 29. 2020

반올림 할 줄 아세요?

사사오입, 오사오입 그리고 코틀린 반올림

요새 핫한 넷플릭스 스위트 홈의 동아시아 평균 평점을 구해보자.

넷플릭스 DB에 등록된 한국, 대만, 몽골, 중국, 홍콩, 일본 평점이 각 5, 5, 5, 5, 5, 2이었고 평점 총합은 27로 집계됐다. 코틀린으로 작성된 프로그램에서 이 값들을 가져와 소수점을 빼고 평균을 내보면 4.0이라는 값이 나온다.


https://gist.github.com/KD4/7152f5f24968da24a682190457711a6b


27/6 = 4.5, 4.5를 반올림하면 4.0? 맞나? 우리는 이 값을 검증하기 위해 MySQL 쿼리로 평균을 구해본다.

이번엔 5.0이라는 값이 나온다. 이 오차는 어디에서 발생하는 것일까?


반올림의 종류

반올림은 크게 두 가지 종류가 있다.


사사오입

1. 반올림 할 자리를 구한다.

2. 4 이하면 0으로 버리고 5 이상이면 0으로 버린 후 윗자리에 1을 더한다.


오사오입

1. 반올림 할 자리를 구한다.

2. 4 이하면 0으로 버리고 5 이상이면 0으로 버린 후 윗자리가 홀수일 때 1을 더한다.


54.5일 때 사사오입 반올림은 55, 오사오입 반올림은 54가 된다.


우리가 사용하는 일반적인 반올림은 사사오입이다. 하지만 공학이나 자연과학에서는 오사오입을 많이 사용한다. 이는 이상하게 생긴 반올림이지만 통계적으로 합리적이기 때문이다.

맨 뒷자리가 필연적으로 손실되는 사사오입 계산 방식보다 수마다 확률적으로 다른 방식을 사용하는 것이 평균의 차이를 줄여줄 수 있다.


이와 관련된 사례로, 오사오입 규약이 제정되기 전 미국 국세청은 사사오입 반올림을 사용하다가 소송을 당한 사건이 있었다. 소송의 내용은 "0.5에 걸친 사람들을 모조리 올림하여 부당하게 세금을 징수했으니 돌려달라"는 거였고 미국 국세청은 패소하였다. 이후 1985년, 오사오입 반올림은 IEEE754 조항에 반올림 규약으로 규정됐고 오사오입 반올림은 뱅커스 라운딩이란 이름으로 돈에 민감한 금융계에서도 사용되고 있다.


그럼 다시 돌아가 넷플릭스 평점의 오차는 어떻게 설명할 수 있을까?

이 오차는 Kotlin의 기본 round 함수는 뱅커스 라운딩(오사오입)을 사용하고 MySQL은 산술적 라운딩(사사오입)을 사용하기 때문에 생긴 오차이다. 컴퓨터로 처리되는 숫자라도 어떤 프로그래밍 언어를 사용하는지에 따라 반올림 결과가 다를 수 있기 때문에 언어별, 소프트웨어별 반올림 방식에 대해서 알고 있는 편이 좋을 것 같다.


출처: https://gall.dcinside.com/board/view/?id=programming&no=1433703


우리가 사용한 코틀린의 round 함수는 뱅커스 라운딩이지만 roundToInt 혹은 roundToLong 함수를 사용하면 산술적 라운딩을 구할 수 있다. 하지만 더 정확한 계산을 위해서는(소수점 반올림이 필요하거나 반올림 오차를 더 줄이기 위하여) BigDecimal.setScale 함수를 사용해 계산하는 게 좋을 것이다.


https://gist.github.com/KD4/b98be3cc9b356ba9b368bb63ff2e5dc4





참조:

https://ko.wikipedia.org/wiki/%EB%B0%98%EC%98%AC%EB%A6%BC

https://gall.dcinside.com/board/view/?id=programming&no=1433703


매거진의 이전글 [읽고서] 자바 고유락과 Synchronization
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari