rlaalswo01   6년 전

이런 식으로 소수점 출력하는 문제, 늘 알고리즘도 맞고 예제 출력도 정상적으로 되는데

채점시 제가 알 수 없는 소수 오차 때문에 오답 판정이 자주 일어나고 애를 먹습니다.

어떤 때는 최대한 int 형으로 커버되는 곳까지 int 형으로 계산하다 (예를 들어 단순 덧셈, 뺄셈 등) int 형으로 더이상 계산이

안되는 지점부터 double 형으로 변환해서 했더니 통과되는 경우도 있고, 또 어떤 경우엔 오히려 그렇게 했더니 

오답판정이 더 빨리 나는 경우도 있고요... 질문 게시판들을 보다보면 double로는 틀렸는데 float로는 통과되더라, 하는식의

글들도 본적이 있어 순 노가다 & 운빨처럼 느껴지기도 합니다... 하지만 고수분들은 이런 어려움을 겪지 않으실것 같아

안전하게 통과할 수 있는 요령이 있는가 싶어 질문 드립니다.

djm03178   6년 전

우선은 실수 연산을 최소화하는 게 최우선입니다. 실수는 연산할 때마다 오차가 날 가능성이 굉장히 높습니다. double이 아무리 정확도를 15자리까지 보장해준다고 해도, 그 오차가 여러 차례 반복되면 어떤 값이 되어 있을지는 예측하기 어렵습니다.

double이 float보다 빨리 틀리는 경우가 간혹 있는 것은 오차가 적다고 해서 반올림한 값이 반드시 정답에 더 가까운 것은 아니기 때문입니다. 예를 들어 소수 셋째 자리에서 반올림해야 하는 문제에서 실제 값이 0.005이면 정답은 0.01인데, 0.0049999999 (double)은 0.0051 (float)보다 오차가 작지만 오히려 double 쪽이 오답을 출력하게 됩니다. 그렇다 하더라도, 일반적으로 double이 정답을 출력할 가능성이 훨씬 높습니다.

특정 문제들의 경우 처음부터 실수형을 일절 쓰지 않고 정수부와 소수부를 나누어서 100% 정확하게 계산할 것을 요구하기도 하는데, 이 문제는 그런 경우는 아닙니다.

최근에는 이런 문제는 거의 스페셜 저지가 구현되어 얼마 이하의 오차를 허용하게끔 되어 있으나, 이 문제처럼 무조건 하나의 답만 인정되는 경우라면 가능한 실수 연산을 줄이고 정확도가 높은 자료형으로 계산하는 것이 최선입니다.

doju   6년 전

답이 분수 꼴로 나타난다면 정수 연산만으로 처리할 수 있습니다.

  • $\frac{a}{b}$를 소수점 이하 셋째 자리에서 반올림한 뒤 100을 곱한 값을 $s$라고 하자.
  • $\frac{s - 0.5}{100} \le \frac{a}{b} < \frac{s + 0.5}{100}$
  • $\frac{100a}{b} - 0.5 < s \le \frac{100a}{b} + 0.5$
  • $s = \lfloor \frac{200a+b}{2b} \rfloor$

예시

  • $a=2$, $b=9$: $\frac{a}{b} = 0.2222\cdots$, $s= \lfloor \frac{409}{18} \rfloor = 22$
  • $a=6$, $b=7$: $\frac{a}{b} = 0.8571\cdots$, $s= \lfloor \frac{1207}{14} \rfloor = 86$

rlaalswo01   6년 전

float 와 double의 오차 예시에서 무릎을 탁 쳤습니다 !

그리고 자리수 올림으로 소수 연산을 피해가는 테크닉 또한 매우 유익한 내용이라는 생각이 듭니다 ^^

피와 살이 될 친절한 답변들 정말 감사드립니다!

댓글을 작성하려면 로그인해야 합니다.