본문 바로가기

Silverlight

[삽질방지] 1.05 != 1.05. 실수의 소숫점 비교의 돌발사항


이번 글 역시 실버라이트 네이버 카페의 쇼티님께서 번역해 주신 자료입니다.

================================================================================================================= 

  어떤 기술은 아니고, 실버라이트 연산상의 버그에 대한 우회 방법이랄까요..

  (http://silverlight.net/blogs/msnow/archive/2008/09/12/silverlight-tip-of-the-day-40-1-05-1-05.aspx)

 

  즉 어떤 이미지를 일정 간격으로 증가시켜야한다고 했을 때, 예를 들어서 ScaleTransform.ScaleX의 경우를 보죠.

  저는 "0.0"에서 "2.0"으로 "0.05"씩 증가시켜야하고, 이 ScaleTransform.ScaleX가 "2.0"이 되었을 때에 체크를 해서

  무슨 처리를 해야한다고 가정을 해봅시다. 근데 문제는 이게 정확하게 "2.0"이 안된다는 것입니다. 소숫점을 Parsing

  하는 부분에서 뭔가 부작용이 발생한다는 것이죠. 예를 들어 디버거로 "1.05"를 검사해보면 실제로는 "1.0499999523162842.."

  뭐 이런 이상한-_- 숫자가 되어 나온다는 것입니다.

   Moral of the story: “Comparing floating point is fraught with peril. Do not rely on comparisons with floats or exact fuzzy with epsilon. That is, floating computation has errors so never do equal comparisons. Also, you should generally never introduce an epsilon and do a fuzzy comparison since it simply pushes your bugs to some other range of numbers you likely don’t test.”

   즉, 이런 식으로 프로그램을 작성하지 말라는 이야기입니다.   

scale.ScaleX = 0.0;

 

while (scale.ScaleX != 2.0)

{

    scale.ScaleX += 0.05;

    // Do stuff here...

}

 

 

  != 기 때문에, 무한루프가 걸릴 소지가 있다는 이야기지요. 아래의 방법을 사용하시면, 소숫점이 어찌되든 상관이 없기때문에,

  이것을 추천드립니다.

scale.ScaleX = 0.0;

 

while (scale.ScaleX < 2.0)

{

    scale.ScaleX += 0.05;

    // Do stuff here...

}


슈퍼울트라 고수이신 공도님에 의하면 원래 double이 가지고 있는 표현 오차상의 문제라고 하네요.
(http://gongdosoft.com/318)

[출처] 실버라이트 네이버 카페