c언어 floating point 관련 질문 입니다.

ydx의 이미지

#include

main()
{
if(0.14*50 == 7)
printf("0.14*50 = 7 %lf\n",0.14*50);
else
printf("0.14*50 <> 7 %lf\n",0.14*50);

if(14.0*0.5 == 7)
printf("14*0.5 = 7 %lf\n", 14*0.5);
else
printf("14*0.5 <> 7 %lf\n", 14*0.5);

}
위와 같이 짰습니다.

결과는 아래와 같습니다.
0.14*50 <> 7 7.000000
14*0.5 = 7 7.000000

왜 이렇게 되는지 도저히 이해가 되지 않습니다.

컴파일러는 gcc 3.4.6 입니다.

부디 간단하게나마라도 설명 부탁 드립니다.

체스맨의 이미지

그건 당연히 그렇게 됩니다. 수학적인 실수는 연속적이지만, 컴퓨터의 floating point 는 불연속적이니까요. 그래서 대개는 오차 범위를 두어 비교합니다. 일반적으로 eps ( epsilon ) 값이라고 부릅니다.

예를 들어 임의 실수 val 이 0 인지 판단하는 코드는 다음과 같습니다. 리터값이 0인 경우 val 을 0으로 판단합니다.

return val>eps? 1 : val<-eps ? -1 : 0;

Orion Project : http://orionids.org

ydx의 이미지

답변 감사드립니다.

코드를 보면 if 구문이 2개로 되어 있습니다.

하지만 첫 번째 if는 7과 다르다고 찍히지만 %lf로 찍히는 값은 7.0 입니다.

두 번째 if는 7과 같다고 찍히며, 역시 %lf로 찍히는 값이 7.0 입니다.

제 느낌으로는 첫 번째 if와 두 번째 if가 같은 결과를 찍어내야 하는데 서로 다른 결과를 찍어 내는 것일까요?

입실론(epsilon)은 우리가 임의로 정해주는 값인가요?

허용 오차범위를 우리가 정해 주는 그런 개념이겠지요?

cwryu의 이미지

0.14라고 쓰면 십진수 0.14가 아닙니다. IEEE754의 구조가 어떻게 되어 있는지 보세요.

ydx의 이미지

#include <stdio.h>
 
main()
{
 
    if(0.14*50 == 7)
        printf("0.14*50 = 7,  %f\n",0.14*50);
    else
        printf("0.14*50 <> 7,  %f\n",0.14*50);
 
    if(50*0.14 == 7)
        printf("50*0.14 = 7,  %f\n",50*0.14);
    else
        printf("50*0.14 <> 7,  %f\n",50*0.14);
 
    if(14.0*0.5 == 7)
        printf("14*0.5 = 7,  %f\n", 14*0.5);
    else
        printf("14*0.5 <> 7,  %f\n", 14*0.5);
 
    if(0.5*14 == 7)
        printf("0.5*14 = 7,  %f\n", 0.5*14);
    else
        printf("0.5*14 <> 7,  %f\n", 0.5*14);
 
}

위와 같이 짜면 아래와 같이 나옵니다.

0.14*50 <> 7,  7.000000
50*0.14 <> 7,  7.000000
14*0.5 = 7,  7.000000
0.5*14 = 7,  7.000000

아무리 생각 해 봐도 output의 각 라인이 같은 내용을 출력해야 하는데 첫 두 라인과 나머지 두 라인이 서로 다릅니다.

왜 그런지 아시는 분 답변 부탁드립니다.ㅠㅠ

ydx의 이미지

cwryu 님 답변 감사드립니다.

금방 IEEE754에 대해서 잠깐 찾아봤는데, 아무래도 0.14는 2진수 형태로 변형하게 되면 2진수 무한소수가 되어 23비트 이하는 잘려버리기 때문 인 것 같습니다.(맞는지요?)

하지만 0.5의 경우에는 무한소수로 되지 않고 딱 떨어지기 때문에 잘리지 않구요.

그렇다면, c언어 내에서 if문 내에서 변수가 아닌 floating point의 상수로 이루어진 수식을 평가할 때, float형, double형 중에서 어떤 형태로 정확도를 줘서 평가하는 것일까요?

아무래도 double형의 정확도로 평가 할 것 같은데..^^; 이부분에 대해 확실히 나와 있는 문서는 어디서 찾을 수 있나요?

마지막으로 printf에서 0.14*50의 값이 7.000000 이 나온 것은 소수점 6자리 정확도에서는 반올림 되어 7.000000 이지만 정확도가 더 늘어나면 다른 값이 출력 되겠지요?

cppig1995의 이미지

정확하십니다.
float=float일 때는 float로, long double=double이나 long double=long double일 때는 long double로 비교하겠죠.



(전략) 항복 권고를 받은 키탈저 태수 아지엣 사카라는 "항복? 먹는 거냐?"라는 짤막한 답장을 써보냈다. 베로시 토프탈은 행간에서 낄낄거림이 묻어나는 문체로 항복은 먹는 것이 아니라 자신의 미력함을 인정하고 상대에게 굴복하는 것이라는 상냥한 답을 보냈다. 그러자 아지엣 사카라는 "못 먹는 것이면 관심 없다."는 답장을 보냈다.
몽화 대사전 - http://cppig1995.n-pure.net/mh

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

peecky의 이미지

그냥 상수를 쓰면 double로, 상수 뒤에 f를 붙이면 float로 인식됩니다.

sizeof 나 컴파일러 워닝으로 대충 짐작도 할 수 있습니다 :)

#include <stdio.h>
 
int main()
{
        printf("%d %d %d %d\n", sizeof(3.14), sizeof(3.14f), sizeof(3.14*3.14f), sizeof(3.14f*3.14f));
        return 0;
}
 
결과:
8 4 8 4

정수형 상수 뒤에도 l, u, ul 등을 붙여서 long, unsigned, unsigned long 등으로 타입을 정해줄 수 있습니다.

댓글 달기

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