호댕의 iOS 개발

[Swift] NumberFormatter roundingMode 본문

Software Engineering/Swift

[Swift] NumberFormatter roundingMode

호르댕댕댕 2021. 11. 21. 21:33

NumberFormatter를 보면 지정한 소수점에 맞춰 어떻게 올림, 버림, 반올림을 할 지 정할 수 있는 인스턴스 프로퍼티가 존재한다. 

 

제목에도 나와있듯 roundingMode가 바로 그것이다. 

 

여기서는 7가지 종류로 어떻게 소수점을 처리할 지 정할 수 있다. 

  • .up
  • .down
  • .ceiling
  • .floor
  • .halfUp
  • .halfDown
  • .halfEven

그렇다면 각각 어떤 식으로 소수점을 처리하는 것일까?

 

.up

Round away from zero.

0으로 부터 멀어지도록 소수점을 처리하게 된다. 

즉 음수일 때는 작아지는 방향으로, 양수일 때는 커지는 방향으로 소수점을 처리한다. 

만약 

let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = 0

이렇게 설정하고 소수점을 처리한다고 생각해보자. 

일단 .maximumFractionDigits을 0으로 잡았기 때문에 소수점은 아예 없애주는 방식으로 소수점을 처리하게 된다. 

 

이 때 roundingMode를 up으로 설정한다. 

numberFormatter.roundingMode = .up

 

그리고 테스트를 해보자! 

let number = -1.000001
let result = numberFormatter.string(for: number)
print(result) // -2

소수점이 비록 0.000001만 붙어있더라도 0과 더 먼 -2로 값을 처리하는 것을 볼 수 있다. 

만약 음수가 아닌 양수였다면 또 0과 더 먼 2로 값이 처리될 것이다. 

 

.down

Round towards zero.

down은 up과 반대로 0과 가까워지도록 소수점을 처리하게 된다. 

즉, 음수일 때는 커지는 방향으로, 양수일 때는 작아지는 방향으로 소수점을 처리하게 된다. 

그럼 예시 코드로 down도 살펴보자

아까와 .maximumFractionDigits은 동일하게 설정했다. 

let number = -1.9999999
let result = numberFormatter.string(for: number)
print(result) // -1

 

만약 1.999999 였다고 하더라도 0과 가까운 1로 소수점이 처리될 것이다. 

 

.ceiling

Round towards positive infinity.

양의 무한대 쪽으로 소수점을 처리한다. 

 

처음에는 이 설명을 보고 잘 이해가 가지 않았다. 

 

그림으로 한 번 살펴보자. 

위에서 .up, .down 같은 경우 양수와 음수가 다른 방향으로 소수점을 처리했다. 

하지만 .ceiling의 경우 둘 다 양수 방향으로 소수점을 처리하게 된다. 

 

.floor

Round towards negative infinity.

.ceiling과 반대로 음수 쪽으로 소수점을 처리한다. 

 

.halfUp

Round towards the nearest integer, or away from zero if equidistant.

가까운 숫자를 향해 소수점을 처리하며 만약 숫자 간의 거리가 동일할 경우 0과 떨어지도록 소수점을 처리하게 된다. 

 

일단 우리가 자주 사용하는 반올림 개념이다. 

5를 기준으로 5 이상이면 올림을 해주고 5 미만이면 버림을 하게 된다. 

여기서 숫자 간의 거리가 동일하다는 말은 만약 0과 1 사이의 소수점 첫째자리일 경우 0.5를 의미하는 것이다. 

(0과의 거리도 0.5이고 1과의 거리도 0.5이다)

 

.halfDown

Round towards the nearest integer, or towards zero if equidistant.

이 또한 가까운 숫자를 향해 소수점을 처리하나 숫자 간 거리가 동일할 경우 0과 가까워지도록 소수점을 처리하게 된다. 

 

즉 0과 1 사이일 경우 

0.5까지는 버림을 하게 되고 0.6부터 올림을 하게 되는 것이다. 

 

.halfEven

Round towards the nearest integer, or towards an even number if equidistant.

가까운 숫자를 향해 소수점을 처리하지만 동일할 경우 바꾸려는 소수점 자리수의 값이 짝수가 되도록 바꿔준다. 

 

기본적으로 roundingMode를 설정하지 않으면 default로 .halfEven이 설정되어 있다. 

 

예시를 통해 살펴보자. 

 

let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = 1
numberFormatter.roundingMode = .halfEven

let number = 0.45
let result = numberFormatter.string(for: number)
print(result)

이 경우 소수점 1자리로 만들어야 하는 상황이고 만약 올림을 하게 되면 0.5, 버림을 하게 되면 0.4가 되는 상황이다. 

 

이 때 .halfEven을 사용하면 만들어야 하는 소수점 자리가 짝수가 되도록 0.4로 변환을 하게 된다. 

 

만약 이 경우는 어떠할까?

let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = 1
numberFormatter.roundingMode = .halfEven

let number = 0.55
let result = numberFormatter.string(for: number)
print(result) // 0.6

이 때는 버림을 하면 0.5, 올림을 하면 0.6이 된다. 

그래서 이 때 .halfEven을 사용하면 만들어야 하는 소수점 자리가 짝수가 되도록 0.6으로 변환을 하게 된다. 

 

즉 바뀌는 자리 수가 짝수가 되도록 올림과 버림 중 선택해서 사용하는 것이다. 

 

일반적인 계산은 아니라고 생각하는데 왜 .halfEven을 roundingMode의 기본 값으로 사용하는지에 대해선 아직 잘 모르겠다..😵

Comments