점수나 금액을 등급별로 나눌 때 Select Case를 많이 쓰는데, 값이 정수가 아니라 소수(Double)일 때는 범위를 적는 방식에 따라 엉뚱한 구간으로 빠지는 값이 생깁니다. 겉보기엔 맞게 짠 것 같은데 특정 값만 Case Else로 가는 경우가 대표적입니다.
To로 범위를 적으면 틈이 생긴다
Select Case aa
Case 1 To 1.49
MsgBox(1)
Case 1.5 To 2
MsgBox(2)
Case Else
MsgBox("was lower than 1 or higher than 2 or between 1.49 and 1.5")
End Select
사람 눈으로는 1~1.49, 1.5~2로 빠짐없이 나눈 것 같지만, Double에는 1.49와 1.5 사이의 값이 얼마든지 있습니다. 실제로 넣어 보면 이렇게 갈립니다.
Dim aa As Double = 1.499 ' Case Else 로 감
Dim aa As Double = 1.4 ' Case 1 To 1.49 로 감
Dim aa As Double = 1.78 ' Case 1.5 To 2 로 감
1.499는 1.49보다 크고 1.5보다 작으니 어느 범위에도 속하지 않고 Case Else로 떨어집니다. 입력값이 사용자가 친 숫자라면 소수 둘째 자리까지만 들어온다고 믿기 쉽지만, 계산 결과(평균, 비율 등)를 넣는 순간 이런 값이 얼마든지 생깁니다.
Case Is <= 로 위에서부터 걸러내기
틈을 없애는 가장 간단한 방법은 경계값 하나만 적고 위에서부터 차례로 거르는 방식입니다.
Select Case value
Case Is <= 49.99
Debug.WriteLine("first group")
Case Is <= 99.99
Debug.WriteLine("second group")
Case Is <= 199.99
Debug.WriteLine("third group")
Case Else
Debug.WriteLine("fourth group")
End Select
Select Case는 위에서부터 처음 맞는 Case 하나만 실행하므로, 두 번째 Case에 도달했다면 이미 49.99보다 크다는 뜻입니다. 그래서 49.995 같은 값도 빈틈없이 두 번째 그룹으로 갑니다. 다만 경계를 49.99로 적었기 때문에 "50 미만"을 의도했다면 49.995가 두 번째 그룹으로 가는 게 맞는지 따져 봐야 합니다. 저는 이런 경우 아예 Case Is < 50처럼 다음 구간의 시작값으로 적습니다. 그러면 경계가 정확히 50이 되어 헷갈릴 일이 없습니다. 음수는 첫 번째 그룹에 포함된다는 점도 알아 두세요.
Select Case True로 조건식 쓰기
각 Case에 아예 조건식을 쓰는 방법도 있습니다. Select Case True로 두고, 처음으로 True가 되는 Case를 실행하게 하는 방식입니다.
Select Case true
Case (value >= 0 andalso value <= 49.99)
Debug.WriteLine("first group")
Case (value >= 50 andalso value <= 99.99)
Debug.WriteLine("second group")
Case (value >= 100 andalso value <= 199.99)
Debug.WriteLine("third group")
Case Else
Debug.WriteLine("fourth group")
End Select
조건을 마음대로 조합할 수 있어 "금액이 100 이상이고 회원 등급이 VIP" 같은 복합 조건에 쓰기 좋습니다. 하지만 이 예제는 첫 번째 방식과 같은 틈을 다시 만들고 있습니다. 49.995나 99.995 같은 값은 어느 조건에도 맞지 않아 Case Else로 가고, 음수도 마찬가지입니다. 이 방식을 쓸 거라면 value < 50처럼 다음 구간의 시작값을 기준으로 미만(<)을 쓰는 게 안전합니다.
구간을 나누는 코드는 짤 때보다 경계값을 넣어 테스트해 볼 때 문제가 드러납니다. 각 구간의 경계 바로 위·아래 값(49.99, 49.995, 50 등)을 몇 개 넣어 보고, Case Else로 빠지는 값이 의도한 것인지 확인하는 습관을 들이면 이런 실수를 거의 막을 수 있습니다.
참고: Stack Overflow - Select Case to check range of a decimal number