gcc에서 실수형은 반올림되어서 저장되나요?

letsdoit의 이미지

flot f = 6.666666666 ;
printf("%f\n", f );
라고 적으니 6.666667 이 출력이 됩니다.
왜그런지 모르겠습니다.
gcc에서는 소수점이하 5자리까지 출력하고 6자리는 7자리
수에 의해서 반올림하는건가요?

litdream의 이미지

음~ 반올림에 관한것은 우선 잘 모르겠고요.
IEEE 의 Floating point 에 관한 규정이 있습니다.

http://stevehollasch.com/cgindex/coding/ieeefloat.html

일단 float 는 4바이트니깐, 영원히 6.66666... 을 저장하지 못하고, 어딘가에서
잘라내거나 반올림을 하거나 결정을 내려야겠지만, 이것이 반올림처럼 보이는지,
아니면 2진수로 32비트를 표현하다 보니 나타나게된 현상인지는 정확히
모르겠군요.

저 주제로 중간고사를 쳤던 기억만이.. 가물가물..

삽질의 대마왕...

cinsk의 이미지

letsdoit wrote:
flot f = 6.666666666 ;
printf("%f\n", f );
라고 적으니 6.666667 이 출력이 됩니다.
왜그런지 모르겠습니다.
gcc에서는 소수점이하 5자리까지 출력하고 6자리는 7자리
수에 의해서 반올림하는건가요?

gcc가 그런 것이 아니고, C 표준이 그렇게 되도록 정의하고 있습니다. 소수점 이하 몇 자리를 출력하라고 지시하지 않았을 때에는 default로 6 자리까지 출력합니다. 그리고, 이 값은 항상 반올림되어서 출력됩니다. [ISO/IEC C Standard 7.24.2.1 8]

letsdoit의 이미지

답변 감사합니다. :D
그런데..다음과 같이 코드를 작성하고 실행하니 전혀 이상한 결과가 나옵니다.
왜 그럴까요.
void main(void)
{
float f=6.123456789123456;
printf("%f\n", f );
printf("%.7f\n", f );
printf("%.10f\n", f );
}

6.123457
6.1234570
6.1234569550

IEEE754포맷에서 소수점 이하가 잘려서 그런건지...
아니면 다른 원이니 있는지 모르겠습니다.
IEEE754에서 수를 모두표현할수 없을때
반올림이나 무조건 자른다고 하는데......
반올림이라는 개념이 이해가 안가네요.
가수부에서 만약에...이진수로
1111111111 1111111111 1110 111111111
이런식으로 나왔을때 IEEE754의 가수부가 23비트라면
23비트이하는 표현할수 없을텐데...
(물론 정확히는 1비트가 없어지니 24비트겠죠?)

위의 이진수에서 반올림 한다면 어떻게 되나요?
골라주세요..1번같기는 한데 확실히 모르겠네요ㅜㅜ

1번. 1111111111 1111111111 1111
2번. 1111111111 1111111111 1110

cinsk의 이미지

혼동하신 것 같습니다.

실제 floating point number(실수)가 어떻게 표현되느냐와, printf()에서 어떻게 출력되느냐는 다른 문제입니다. 앞에서 제가 반올림된다고 쓴 것은, 실제 어떤 식으로 저장되느냐와는 상관없습니다. 단지 어떤 실수값을 printf()로 출력할 때, 반올림되어 출력된다는 뜻입니다.

참고로 실제 어떻게 표현되는지 알아봅시다:

$ cat tmp.c
int
main(void)
{
  float f;
  double d;
 
  return 0;
}
$ gcc -g3 tmp.c
$ gdb a.out

까지 실행한 다음,

(gdb) br main
Breakpoint 1 at 0x804834c: file tmp.c, line 9.
(gdb) r
Starting program: /some-path/a.out
 
Breakpoint 1, main () at tmp.c:9

위와 같이 main()에 breakpoint를 걸고 실행한 다음,

(gdb) p sizeof(float)
$1 = 4

즉, float이 4byte인 것을 확인하고,

(gdb) p f = 6.123456789123456
$2 = 6.12345695

float type 변수 f에 주어진 실수 값을 대입하고,

(gdb) x /tw &f
0xbff1d274:     01000000110000111111001101011100

그 값을 이진수로 출력하면, (여기서 'x'는 dump 명령 't'는 binary 출력, 'w'는 크기가 word, 즉 4 byte를 의미합니다.)

조금 더 실험하면,

(gdb) p f = 0
$3 = 0
(gdb) x /tw &f
0xbff1d274:     00000000000000000000000000000000
(gdb) p f = 0.01
$4 = 0.00999999978
(gdb) x /tw &f
0xbff1d274:     00111100001000111101011100001010
(gdb) quit
The program is running.  Exit anyway? (y or n) y
$ _

그럼 이만.

cinsk의 이미지

참고로 (제 기억에 맞다면) C 언어에서 쓰는 float point는 IEC 60559를 따를 겁니다.

float, double, long double이 각각 그 spec의 single, double, extended format에 해당합니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.