좀 난감한 부동소수점 문제 질문드립니다.

munamuna의 이미지

이거참.. 질문을 쓰긴 씁니다만 뭐라 써야 잘 표현이 될지도 난감하군요.

일단 내용을 말씀드리도록 하겠습니다.

지금 하는 일이 전력관련 일이라 최대 소수점 4자리까지 계산하는 경우가 많습니다.

어느날 처리된 데이터와 출력값을 보니 일치하지 않는다 하여 찾아봤더니..

0.2가 되어야할 데이터가 무슨 이유에선지 0.1이더군요.

디버깅을 해보니 문제는 사사오입이었습니다.

데이터 double dx가 있다고 가정했을때, 이 dx를 필요에 따라서 소수점 1~5자리까지 위치를 지정해서 사사오입을 합니다.
(사사오입하는 매크로 PP를 만들어서 쓰고 있습니다)

여기에 출력할땐 소수점 첫째자리에서 저기에 출력할때 소수점 셋째자리에서 사사오입을 하는 것이지요.

그런데, 공교롭게도 문제인 데이터 dx는 0.15였고, 더욱 공교롭게도 사사오입 위치는 소수점 2째자리 였습니다.

MSDN을 뒤져보니 부동소수점 표현상의 문제로 (dx = 0.15)는 => (dx = 0.1499999999999999..) 가 되어 메모리에 저장되더군요..

이걸 소수점둘째자리 위치인 4를 사사오입을 해버리니, 0.2가 되어야 할 데이터가 0.1이 되어버리고 만것입니다. @.@);;;

여기서부터 질문입니다만..

1) 일단 사사오입 하기전에 0.000001을 더한후에 하기로 정했습니다.
출력을 소수점 4자리까지 쓰니 사사오입 위치는 최대 소수점 5자리까지가 되므로 안전하게 한자리 더해서 0.000001을 더하기로 했습니다. 문제 없겠지요?

2) 대체 왜 0.15가 0.149999999.., 0.3이 0.299999999 이런식으로 저장이 되는 것인지요?
옛~~~날에 전산학 시간에 들었던 기억이 어렴풋이 납니다만.. 웹을 뒤져도 검색능력이 부족한 것인지 키워드가 안맞는 것인지..
2진수로 표현해가며 알기쉽게 설명나온곳을 못찾겠습니다. 설명이나 링크좀 부탁드리겠습니다.

그럼.. 언제나 즐거운 개발되십시요~. ^^

sephiron의 이미지

1) 아뇨, 그렇게 해도 문제가 생길 가능성이 높습니다.
2) http://kldp.org/node/95199 참고하세요

terzeron의 이미지

그렇게 중요한 소수값을 사용하신다면 GMP 라이브러리를 사용하세요.

esrevinu의 이미지

#include <stdio.h>
 
int main()
{
  double f = 0.1499;
 
  printf("%.2f ~ %f\n", f, (int)(f*10+0.5)/10.0);
 
  return 0;
}

문제가 이런 건가요? 처음에 보여 줄 때는 소수점 둘째자리만 보여 주니까
셋째자리에서 반올림해서 보여 줄테니 0.15가 나오고요,
다음은 소수점 둘째자리에서 반올림해서 0.1이 나오고요.
저기 f에다가 0.15를 넣어 봤는데 0.2가 나오네요. 시스템마다 다를 수 있겠지만요.

drinkme의 이미지

소수점 이하 각 자리의 숫자가 그렇게 중요하다면,
고정소수점으로 접근하시는 것이 좋을 듯 합니다.

juneaftn의 이미지

google "What Every Computer Scientist Should Know About Floating-Point Arithmetic"

asiawide의 이미지

10진수를 2진수로 표현하려면 소수점의 경우 각 자리(0또는 1)에
1/2, 1/4, 1/8,... 을 곱한 식으로 표시가 됩니다.

0.3 은 0*1/2 + 1*1/4(0.25) + 0*1/8 + 0*1/16 + 1*1/32 +...
이런 식으로 0.3에 근사하는 값으로 표시가 됩니다.

klyx의 이미지

최대 소수점 자리수가 네자리로 정해져있다면, 전부 10만배나 100만배한후 정수로 계산하고, 마지막에 10만(혹은 100만)으로 나누는게 가장 간편하고 빠르고 정확할듯합니다. 정수범위가 모자르면 64비트정수형 쓰면되구요.

munamuna의 이미지

한분한분 조언 감사드립니다.

웬지.. 더욱더 미궁으로 빠진듯한 기분입니다만... ㅠ.ㅠ;

수업을 충실하게 안들은 제 잘못이니 좀더 공부하도록 하겠습니다.

답변 감사드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.