C에서 double에 대한 질문입니다.

푸르미의 이미지

C 에서 double 5.4를 binary로 출력해보니

Quote:
0 10000000001 0101100110011001100110011001100110011001100110011010

가 나왔습니다.
즉 가수부는
Quote:
0101100110011001100110011001100110011001100110011010

가 되죠

main()
{
double a = 5.4;
long long int * b = (long long int*)(double*)&a;
printf("%f %x\n", a, b);

long long int c = *b;
int i;

for(i=0; i<64; i++)
{
if(i == 1 || i == 12) printf(" ");
printf("%d", (c>>(63-i))&0x1);
}
printf("\n");
}

그런데 자바스크립트로 이런 데이터를 만들어보니
(http://purmi.org/work/ide/kk.html)
가수부가

Quote:
0101100110011001100110011001100110011001100110011001

가 나옵니다.

위의 것과 밑의 것을 비교하면 끝에 두 수만 다릅니다.
이것이 항상 그런 것은 아니고 몇 가지 수에서만 그렇습니다.
그 몇 가지가 몇 가지일지 몇 십가지일지는 저도 모르겠습니다.

왜 이런 결과가 나온 걸까요?

뭔가 잘못 처리한 걸까요? 아니면 C언어에서 반올림처리하는게 있는걸까요?

Anonymous1의 이미지

대부분의 10진 실수는 2진수로 완벽하게 표현할 수 없습니다. 아마도 그 때문에 일어나는 일인 듯 하군요.

컴파일러 (혹은 자바스크립트 번역기)가 소스 코드의 10진 상수 5.4를 읽어들여 내부적으로 2진수로 변환하는 과정에서, C 컴파일러와 자바스크립트가 서로 다른 방식으로 동작하는 듯 합니다.

푸르미의 이미지

5.4의 경우 0.4를 2진수로 취하면 0. 이후 0110이 반복되는 수가 됩니다. 2진 순환소수일까나요.. 그런데 C 에서는 0110이 반복되다가 0110의 형태가 아닌 10으로 끝나더군요. 정확하지 않다고는 하나 어떤 식으로 처리하여 그런 결과가 나온 것인지 궁금한 것입니다.

http://purmi.org/work/ide/kk.html

Quote:
<html> <head> <script type="text/javascript"> function a() { var aa = document.getElementById("aa"); var data = aa.value; var k = to_binary(data); var a = 0.000000476837158203125; var b = a * 2097152;

var s = a + " " + b + " " + k;
}

function to_binary(d)
{
var is_minus = 0;
if(d.substring(0,1) == '-')
is_minus = 1;

var point = d.indexOf('.');
if(point == -1)
point = d.length;
var str1 = d.substring(is_minus, point);
var str2 = d.substring(point+1);

var b1 = to_b1(str1);
var b2 = to_b2(str2, b1.length);

var bb = b1 + " " + b2;
document.getElementById("bb").value = bb;
return 0;
}

function to_b1(str)
{
var d = "";
var b, b1;
b = str;
while(b!=0)
{
b1 = b % 2;
b = Math.floor(b / 2);
d = b1 + "" + d;
}

return d;
}

function to_b2(str, int_length)
{
var total_length = 52 - (int_length - 1);
var d = "";
var b, b1;
b = "0." + str;
var len = 0;
var cc = document.getElementById("cc");
var ccv = "";
while(b!=0 && len {
b = b * 2;
ccv = ccv + " " + b;
b1 = (b+"").substring(0,1);
d = d + "" + b1;
b = b - b1;
ccv = ccv + " " + b + "\n";
len = len + 1;
}
cc.value = ccv;

return d;
}

</script>
</head>
<body>
<input type="text" id="aa">
<a href="javascript:a();">test</a><br>
<input type="text" id="bb" style="width:500px;"><br>
<textarea id="cc" style="width:500px; height:500px;">
</textarea>
</body>
</html>

++++++++++
學而時習之

Anonymous1의 이미지

님의 코드는 자바스크립트에서 내부적으로 5.4를 저장하는 방식을 보여주는게 아니라, 그냥 5.4를 이진수로 바꾸어서 52자리까지만 보여주는 코드일 뿐입니다.

사실, 자바스크립트는 메모리에 대한 직접 접근을 허용하지 않으므로, 자바스크립트 내부에서 5.4를 어떻게 저장하고 처리하는지 알 수 있는 방법은 전혀 없습니다.

IEEE 754를 제대로 구현했다면, C와 같은 결과가 나와야 맞습니다.

http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html

위에서 제시하신 두가지 경우의 차이는, 단지 어느 자리에서 반올림을 하는가의 차이일 뿐입니다.

Anonymous1의 이미지

그냥 이쪽이 더 이해하시기 편하시겠군요.

http://www.h-schmidt.net/FloatApplet/IEEE754.html

맨 끝자리 비트를 01로 하는 것과 10으로 하는 것 중 어느 쪽이 더 5.4에 가까우신지 직접 보시면 되겠군요.

lifthrasiir의 이미지

자바스크립트(정확히는, ECMAScript)와 C/C++는 둘 다 IEEE-754 부동 소숫점 표현을 사용합니다만 거기에 대한 스펙은 상당히 다릅니다. IEEE-754는 표현 형식 뿐만 아니라 거기에 따라 가는 연산(덧셈, 곱셈, 제곱근 등)에 대한 규칙이 정리되어 있는데, 둘은 rounding method에서 다음과 같이 다릅니다.

  • (익명께서 말씀하신 것과는 다르게) ECMAScript는 무조건 round to nearest(가까운 쪽으로 반올림)입니다.
  • C/C++는 implementation defined입니다. (float.h에서 FLT_ROUNDS를 보면 기본값이 어떤 방식인 지 알 수 있습니다.) 단 제 노트북에서는 마찬가지로 round to nearest군요.
따라서 두 구현체의 rounding method가 다르다면 다른 결과가 충분히 나올 수 있습니다. 물론 그렇다고 해서 푸르미 님의 스크립트가 실제로 "어떻게 저장되는 지"를 보여 주는 건 아닙니다만...;;

- 토끼군

푸르미의 이미지

답해주셔서 감사합니다.

그런데, 혹시 IEEE 754에 대한 자료를 가지고 있으신가요?
있다면, 좀 주셨으면 합니다.
대충은 무슨 소리인지 알겠는데, 어떻게 정의되어 있는지 한 번 보고 싶습니다.

++++++++++
學而時習之

cinsk의 이미지

google에서 "ieee 754"로 검색해 보세요.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

댓글 달기

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