제가 3회 코딩테스트 문제에 출제했던 가희와 무궁화호는 처음에 실수 민감형이였습니다. 어떤 버전이였는지는 old version의 코드를 보시면 대략 감이 오실 듯 싶어요. 부동 소수점은 0.1, 0.2 등을 정확하게 저장하지 못합니다. 정확하게 저장하려면 고정 소수점 등을 이용해야 합니다.

 

 파이썬에서는 Decimal을 쓰면 그러한 일을 할 수 있습니다. 당연하게도 현재 버전의 풀이가 아닙니다. 이 글에서는 단지, 엄청나게 작은 오차도 허용하지 말아야 하는 경우에 파이썬에서는 어떻게 해야 하는지에 대해서만 언급하겠습니다.

 


24336번의 원래 버전은 눈치 채셨겠지만, 표정 속도를 소수점 첫째 자리에서 버림한 값을 출력하라 했습니다. 이게 실수 민감형인가요? 라고 물어보실 수도 있습니다만, 매우 쉽게 실수 오차를 고려하지 않은 코드를 저격을 할 수 있습니다. 예를 들자면, 옥천에서 대전까지 12분이 걸리는 데이터를 생각해 봅시다.

 

 

 이 코드는 구간에 대한 정보와 소요 시간을 입력받아서, 표정 속도 (km/h)를 구하는 프로그램입니다. 소수점 첫째자리에서 버립하고요. 옥천역까지 거리는 182.5km, 대전역까지 거리는 166.3km이고, 이 두 역을 가는 데 걸리는 시간이 12분이였다고 해 보겠습니다. 의도한 대로라면, 16.2km를 가는 데 걸린 소요 시간이 12분이므로 81이 나와야 할 겁니다.

 

 

 그런데 80.0이 나오네요? 이는 182.5와 166.3이 저장될 때 약간의 오차가 있었기 때문입니다. 어떻게 해야 할까요? Decimal을 이용해서 고정 소수점으로 받아버려야 합니다.

 

 

 string으로 입력 받은 다음 Decimal에 넣어버립니다. Decimal은 -나 //, %와 같은 연산이 되니, 그대로 계산만 해 주면 됩니다.

 

 

 182.5 166.3 12를 넣었더니 의도한 결과값인 81이 나옵니다.

 

 


 그런데, 만약에 옥천에서 대전까지 12분이 걸렸다는 정보가 들어오면 어떨까요? 혹은 대전에서 옥천까지 12분이 걸렸다는 정보가 들어오면? 절댓값이 필요합니다.

 

 

 이럴 때에는 그냥 abs 메서드를 호출하면 됩니다. Decimal에 Decimal을 뺀 건 Decimal이 되고, 이것을 인자로 받는 abs 함수가 절댓값을 리턴하기 때문입니다. 문서를 보면 알 수 있습니다. 이제 간단한 테스트 케이스를 넘겨 봅시다.

 

 

 서울역으로부터 거리가 0.0인 역으로부터 9.1인 역까지 5분이 걸렸다면, 표정 속도는 109.x km/h가 됩니다. 소수점 첫째 자리에서 버림하라고 했으므로 109가 답이 되겠네요. 테스트는 통과합니다.

 

 


 이제, 이 코드를 Decimal을 이용해서 깔끔하게 바꿔보도록 합시다.

 

 먼저 init_gyeongbu_line_station_info 함수입니다.

 

 

 35번째 줄과 37번째 줄을 보면, conv 대신에 Decimal을 넣었음을 볼 수 있습니다. 기존에 있었던 conv 함수는 필요 없었네요.

 

 

 그러면 쿼리에서 거리를 계산하는 부분은 건드릴 필요조차 없겠네요.

 

 

 실수 민감형 문제에 대해 간단하게 테스트 해 보니, 테스트를 통과함을 알 수 있습니다.