[C++] IEEE754 부동소수점 규약(float 최대값 관련)

gyxor의 이미지

IEEE754 부동소수점 규약에 정의된 float의 범위는
2^-126 ~ (2-2^-23)*2^127 입니다.
이중 최대값을 공학계산기로 구했습니다.

#include<iostream>
using namespace std;

int main()
{
float f= 3.4028234663852885981170418348445e+38;
cout << f << endl;
return 0;
}
7번째 자리에서 반올림해서 빨강색 끝의 3은 사라지고..
3.40282e+038
이렇게 출력이 됩니다. 가수부분이 23bit이므로
2^23 은 8388608 이 되고 이는 7자리 숫자를 제대로 표현 못하므로
유효 숫자가 6자리가 되는것은 알겠습니다.
위 빨강색부분의 숫자를 1만큼 높이면 Infinite가 됩니다.
하지만 그 이후의 숫자는 높이더라도 결과값에 영향을 미치지 않습니다.
다시말해
123456789 와 같은 숫자는 출력해보면 앞에서부터 7자리에서
반올림해서 1.23457e+008 가 되는것입니다.
가수부분에 해당하는 10진수 6자리 값을 원래의 값에서 추출하는
것으로 보입니다.

첫째,
그런데 부동소수의 범위가
2^-126 ~ (2-2^-23)*2^127 인데요..
소수의 범위가 무한이기도 하지만 위 범위는 불연속이 되는데요..
최소값은 차지하고서라도.. 어짜피 불연속이라면..
왜.. 최대값이 (2-2^-23)*2^127 인지 모르겠습니다.
6자리 유효숫자를 생각해서..또한 지수부분의 최대값 127을 적용해서
최대값을 9.99999 * 2^127으로 잡을 수 도 있는것 아닌가요?
이보다 작은 범위로 최대값을 설정한것은 IEEE754에서 정했기 때문인가요?

둘째,
#include<iostream>
using namespace std;

int main()
{
float f= 3.4028234663852885981170418348445e+38;
float b= 34028234663852885981170418348445;
cout << a << endl;
cout << b;
return 0;
}
Compiling...
Cpp1.cpp
D:\user\Nearwater\Cpp1.cpp(7) : error C2177: constant too big
D:\user\Nearwater\Cpp1.cpp(8) : error C2065: 'a' : undeclared identifier
Error executing cl.exe.

Cpp1.exe - 2 error(s), 0 warning(s)
위 소스에서 b값은 f값보다 작지만 에러가 납니다.
f는 저장이 되기전에 미리 유효숫자범위만큼 추출하기 때문에
그런것인가요?
b의 경우엔 19자리 이상이되면 에러가 납니다. 변수값이 메모리상에
저장이 되는 크기가 정해져 있기 때문에..그런것인가요?
vc6.0에서만 그런것인가요?
왜 이런현상이 일어나는지 모르겠습니다.

doldori의 이미지

1. 가수부 23비트가 모두 1일 때의 10진수값은 9.9999가 아니지요. 이 값은
2 - 2^(-23) 이 되고 이를 십진수로 표현하면 1.9999...쯤 됩니다. 여기에 지수
2^127을 곱하여 FLT_MAX가 계산되는 것입니다.

2. 34028234663852885981170418348445은 부동형 상수가 아니라 정수형
상수입니다. 그런데 님의 환경에서는 정수형으로 표현할 수 있는 값을 초과하므로
발생하는 에러입니다. 34028234663852885981170418348445.f
하여 부동형 상수임을 명시하면 될 것입니다. 단, 유효 숫자 이상의 정밀도는
표현하지 못합니다.

gyxor의 이미지

두번째답변은 제가 실수했습니다. 정수형이니까 당연히..^^;
그런데 첫번째 질문은 전달이 좀 잘못된거 같아서
다시한번 질문드리겠습니다.
#include<iostream>
using namespace std;

int main()
{
float a=1E+38;
cout << a;
return 0;
}
이러한 소스는 정상수행됩니다.
float의 범위를 벗어나지 않는 a변수입니다.
38+127 = 165 이고 이를 이진수로 바꾸면
10100101입니다.
이 범위는
Positive Normalized
1.m × 2(e-127) 에 속하므로..
기본적으로 1이 있다고 생각하고..Mantissa는 모두 0입니다.
부호 지수 가수
0 10100101 00000000000000000000000

그런데..
여기서
float a=1E+39;로 바꾸면 INF가 되어버립니다.
부호 지수 가수
0 10100110 00000000000000000000000
이렇게 표현이 가능한데 말입니다.....
결국 이렇게 float의 범위를 제한해 놓은것은
비트범위의 한계 때문이 아니라.. 다른이유인거 같은데요..
그이유가 무엇인지 궁금합니다.

progcom의 이미지

표기에서 착각을 하신것 같은데...
1E+38 은 10의 38승입니다.

doldori의 이미지

좀 더 부연하면 E38 --> E39 로 된다는 것은 2가 아니라 10을 곱한다는 뜻입니다.
따라서 IEEE 754 표기 방식에서 단순히 지수부가 1이 커지는 것이 아니지요.

gyxor의 이미지

float 부동소수의 0부터 ~ 최대값을 살펴봤습니다.
3.40282e+038
[부호][지수] [가수]
0 11111110(254=>127승)1.11111111111111111111111
.
.
.
.
16777218
0 10010111(151=> 24승) 1.00000000000000000000001
16777216
0 10010111(151=> 24승) 1.00000000000000000000000
16777215
0 10010110(150=> 23승) 1.11111111111111111111111
5
0 10000001(129=> 2승) 1.01000000000000000000000
4
0 10000001(129=> 2승) 1.00000000000000000000000
3.12345557
0 10000000(128=> 1승) 1.10001111110011010110010
3.12345556
0 10000000(128=> 1승) 1.10001111110011010110010
3.12345555
0 10000000(128=> 1승) 1.10001111110011010110010
3.12345554
0 10000000(128=> 1승) 1.10001111110011010110010
3.12345553
0 10000000(128=> 1승) 1.10001111110011010110010
3.12345552
0 10000000(128=> 1승) 1.10001111110011010110001
3.12345551
0 10000000(128=> 1승) 1.10001111110011010110001
3.12345550
0 10000000(128=> 1승) 1.10001111110011010110001
3
0 10000000(128=> 1승) 1.10000000000000000000000
2
0 10000000(128=> 1승) 1.00000000000000000000000
1
0 01111111(127=> 0승) 1.00000000000000000000000
0.5
0 01111110(126=> -1승) 1.00000000000000000000000
0
0 00000000( 1=>-126승) 0.00000000000000000000000

제가 궁금했던 부분은
어짜피 빨강색과 오렌지색 부분에서.. 불연속이 발생하는것과
또한
파랑색 부분에서 16777217을 표현하지 못하는..
이러한 불연속을 인정하고 구조를 세운다면..
차라리
지수부분을 2의몇!승 으로 보지 않고 E(10의 몇!승) 으로 판단하면
더 큰 수를 표현 할 수 있지 않을까 하는것이었는데요..
지수가 1증가할때마다 2씩 곱해지는게 아니고 10씩 곱해지므로
불연속 간격이 심하게 커지겠네요..
2의 승수로 보는것이 옳겠군요..
좋은 답변감사드립니다.^^

댓글 달기

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