이건 파이썬이라서 발생한 문제는 아니겠지만 어쨌든 코드를 파이썬으로 하다가 만난 문제다.

지금 만든 프로그램은 f(x)의 평균값을 구해야 한다. 간단하게 x*f(x)를 x에 대해 다 더하고, f(x)를 x에 대해 다 더한 후 둘을 나눠주면 된다.

    for m in range(wbegin,wend):
        for n in range(hbegin, hend):
            x=x+m*array[n][m]
            y=y+n*array[n][m]
            total=total+array[n][m]
    x = x/total
    y = y/total
    return x, y

문제는 x*f(x)를 다 더했더니 overflow가 나 버린다는 것. f(x)중에 음수가 하나도 없고 x도 음수가 하나도 없는데 음수가 나오길래 왜그런가 했더니 x*f(x)를 다 더하다 보니 정수의 한계를 넘어가서 음수부터 다시 시작한 것 같다. (양수를 계속 더했는데 음수가 나오는 경우는 수학적으로는 불가능하니까.)

그래서 이 문제를 해결하기 위해 f(0)부터 시작해서 재귀적으로 계산하여 f(x)까지의 평균을 알 때 f(x+1)까지의 평균을 계산하는 방법으로, 점화식으로 문제를 해결하려고 했다. 이러면 계속해서 나눠주기 때문에 int의 최대값을 넘어가지는 않을 거라고 생각했다. 그러나... 그것은 순진한 생각이었다.
이번엔 f(0)=0에서 시작하는 경우가 문제가 된다. 초항이 0이라 0으로 나누는 오류 발생.
    for m in range(wbegin,wend):
        for n in range(hbegin, hend):
            x=(x*total+m*array[n][m])/(total+array[n][m])
            y=(y*total+n*array[n][m])/(total+array[n][m])
            total=total+array[n][m]
    return x, y

아... 뭐 이래 -_-;

아무튼, 그래서 total = 1로 줬더니 계산은 되는데 오차가 커진다. total = 0.000000000000000001로 주는 무리수를 둬야 하나...

신고
by snowall 2011.07.11 11:22
  • solariser 2011.07.11 12:15 신고 ADDR EDIT/DEL REPLY

    docs.python.org/tutorial/floatingpoint.html#representation-error오잉 숫자가 어마어마 하게 크더니 작거나하지 않으면 별문제 없을텐데 신기하네요 혹시 int로 지정하셨으면 long으로 바꿔보세요~

    • snowall 2011.07.11 19:15 신고 EDIT/DEL

      저도 신기했어요. 초기값을 0 대신 0.0으로 지정했더니 잘 됩니다. 감사합니다~

    • snowall 2011.07.13 23:22 신고 EDIT/DEL

      아, 어마어마하게 큰 이유가
      부호없는 16비트 정수를 40000개 더하는 경우라서, 값들이 다들 큰 경우에는 32비트 한계를 넘어가는 경우가 가능해집니다.

  • goldenbug 2011.07.11 12:41 신고 ADDR EDIT/DEL REPLY

    초항만 예외로 처리해야 할 것 같은데요. ^^;

    • snowall 2011.07.11 19:16 신고 EDIT/DEL

      위의 알고리즘을 써먹을 일이 있다면 초항만 예외로 처리해야겠죠. 아무튼 해결 했습니다

  • 꼼지락 2011.07.13 23:09 신고 ADDR EDIT/DEL REPLY

    for문안에서 x,y를 동시에 구하면 메모리를 더 잡을테니, 각각따로 구함이 더 좋지 않을지요?

    • snowall 2011.07.13 23:19 신고 EDIT/DEL

      어차피 x랑 y랑 한칸씩밖에 차지하지 않아서 괜찮아요
      만약 따로 구한다면
      total = 0
      for m in range(wbegin,wend):
      for n in range(hbegin, hend):
      x=(x*total+m*array[n][m])/(total+array[n][m])
      total=total+array[n][m]
      total = 0
      for m in range(wbegin,wend):
      for n in range(hbegin,
      y=(y*total+n*array[n][m])/(total+array[n][m])
      total=total+array[n][m]
      return x, y

      이런식으로 만들어야 해서 더 이상해져요...;;