[C++] float형 실수를 ieee 754 표준형의 형태로 저장하려는데 문제가 있습니다.

kjw4569의 이미지

cin >> floatNum
unsigned __int64 intNum = (unsigned __int64)floatNum;	//정수부
floatNum -= (float)intNum;				//소수부만 남김
 
for (i = 0; i < len; i++) {			//정수부를 이진수로 변환
    if (intNum == 0)
        break;
    arr[i] = intNum % 2;
    intNum /= 2;
}

사용자로부터 실수를 입력받아 floatNum에 저장합니다.

그리고 floatNum의 정수부와 실수부를 분리해서 각각 이진수로 bool 배열에 저장하려고 합니다.

문제는 아주 큰 수가 입력되었을 경우입니다.

1번 줄에서 부호없는 8바이트 정수형을 써봐도 최대 2^64까지밖에 저장이 안 되네요. 실제로 float형은 2^128까지 표현할 수 있는데 말이죠.

디버그 걸어놓고 floatNum을 살펴보면 큰 수 까지도 제대로 저장이 되는걸 보면 cin 함수는 도대체 어떤 방식으로 작동하는 건지 궁금하기도 하고..

어떤 방법을 써야 할까요?

(* 모호한 표현이 있어 제목을 수정했습니다.)

ifree의 이미지

8바이트 정수형을 쓰면 최대 2^64까지밖에 저장이 안 되는게 당연하죠.
float형이 2^128까지 표현할 수 있는 것과는 무관합니다.

실수는 지수부와 가수부로 나누는 방식으로 아주 작은 수와 아주 큰 수를 표현하는 것입니다.
따라서 정수로 표현할 수 없는 범위의 실수를 정수로 변환하면 당연히 오버플로우가 발생하겠죠.

jick의 이미지

그나저나 float형 변수는 이미 데이터를 IEEE 754 표준에 따라 저장하고 있는 변수입니다.

float를 IEEE-754로 *변환해서* 저장한다는 말은 뭘 하시려는 건지 잘 이해가 안 가는데요.

kjw4569의 이미지

예를 들어 7.0의 경우, 1.11×2^2 이므로 32 길이의 bool 배열에

부호  지수         가수
   0  | 10000001 | 1100 0000 0000 0000 0000 000

의 형태로 저장하려는 것입니다.

zbp의 이미지

unsigned int intNum = *((unsigned int*) ((void*)&floatNum));
설명) 두 번째 줄에서 unsigned int로 캐스팅하면 캐스팅룰에 의해 2^64를 초과하는 값에 대해서는 값이 보존되지 않습니다.
floatNum의 주소를 void*로 캐스팅하면 타입 정보가 사라지고, 여기서 다시 (unsigned int*)로 캐스팅하면 floatNum의 주소를 unsigned int 타입의 4바이트 데이터가 들어있는 것으로 간주합니다. 마지막으로 디리퍼런싱해주면 끝나겠죠.

DarkSide의 이미지

실수의 구조를 무시하고 그대로 캐스팅한다고 해서, 지수부가 저장되는 것은 아닙니다.
글을 상상으로 쓰지 마세요.

jick의 이미지

제가 뭘 놓치는 걸 수도 있지만, 실수의 bit pattern을 그대로 읽으려면 저런 식으로 많이들 할 텐데요.

* 물론 C의 undefined behavior를 사용하는 것이기 때문에 최적화 옵션을 주면 코드가 나가리 날 수 있겠습니다만.

kjw4569의 이미지

int temp = *(int*)&floatNum;
for (int i = 0; i < sizeof(float)*8; i++)
    arr[i] = (temp & (1 << i)) >> i;

제가 과제를 수행하고 있는지라..

아래와 같은 로직을 사용하지 않으면 (정수부는 2로 나누고, 소수부는 2를 곱해나가는)

교수님께 반칙이라고 지적을 당할 것 같습니다.

for (i= 0; i < len; i++) {	  //정수부 기록
    if (intNum == 0)
        break;
    arr[i] = intNum % 2;          **intNum이 어떻게든 2^64를 넘을 수 없기 때문에 문제 발생**
    intNum /= 2;
}
memmove (arr+(len-i), arr, i);    //정수부를 최상위로 옮김
i = len - (i + 1);		  //소수부를 기록하기 위해 인덱스를 정수부의 최하위로 이동	
int point = i;			  //소수점 위치 저장
 
for (; i >= 0; i--) {		  //소수부를 이진수로 변환
    arr[i] = (floatNum *= 2);
    floatNum -= arr[i];
    if (floatNum == 0)
        break;
}
sudo normalization(arr);    //정규화 과정
kjw4569의 이미지

https://sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/vfscanf.c;h=e0d224530cc67498c3fa5b37838d5bdcdf08eb28;hb=HEAD#l2332

scanf 소스를 찾았는데오, strtof 함수를 쓰는걸 보니 역시 정수를 통째로 받으면 안 되고 문자열로 입력받도록 수정해야겠습니다.

좀 복잡해지겠네요.

DarkSide의 이미지

그냥 실수의 해당 비트들을 추출해서 비트 연산으로 간단하게 되지 않나요?

kjw4569의 이미지

과제를 수행중이기 때문에.. 교수님께 반칙이라고 지적을 당할 것 같습니다.

 의 이미지

구체적인 상황에 따라 다르긴 합니다만, 일반적으로 생각해 봤을 때 십진 실수를 문자열로 입력받아서
그걸 IEEE754 이진 부동소수점 포맷으로 변환하는 건 과제 치고는 제법 번거로운 코드가 될 겁니다.

물론 하려고 들면 못 할 건 없는 일이긴 합니다만, 저라면 그걸 시작하기 전에 담당 조교님께 문의를 드린다던가 해서 과제 취지를 분명히 확인해보고 시작할 것 같은데요.

시간이 많으셔서 한 번 해보고 싶으시다면 물론 애써 말릴 생각은 없습니다. 좋은 연습이기는 하니까요.

댓글 달기

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