#include <stdio.h>
#include <tchar.h>
#include <math.h>

#define LENGTH       32
#define SIGN_BIT     31
#define EXPONENT_MSB 30
#define EXPONENT_LSB 23
#define MANTISSA_MSB 22
#define MANTISSA_LSB  0

float hex_to_float (unsigned int value)
{
 int   sign;
 int   exp;
 int   man;
 float result;

 sign = (value & (1 << SIGN_BIT)) != 0;
#pragma warning( push )
#pragma warning( disable : 4307 ) // '-' : integral constant overflow.
 exp  = ((value & ( (2<<EXPONENT_MSB) - (1<<EXPONENT_LSB) )) >> EXPONENT_LSB)
  - (1 << (EXPONENT_MSB - EXPONENT_LSB))
  - (MANTISSA_MSB - MANTISSA_LSB);
#pragma warning( pop )

 man  = ((value & ( (2<<MANTISSA_MSB) - (1<<MANTISSA_LSB) )) >> MANTISSA_LSB)
  + (2 << (MANTISSA_MSB - MANTISSA_LSB));

 result = man * pow((float)2, (float)exp) * (sign ? -1 : 1);

 return result;
}

int _tmain(int argc, _TCHAR* argv[])
{
 union
 {
  unsigned int n;
  float        f;
 } value;

 int   i;
 float f;


 value.f =(float)   0;
 f       =(float)-1.1;

 for (i=0; i<10; i++)
 {
  printf ("%+e=0x%08x:hex_to_float()=%+e \r\n", value.f, value.n, hex_to_float(value.n));
  value.f += f;
 }

 return 0;
}
-----------------------------------------------------------------------------
+0.000000e+000=0x00000000:hex_to_float()=+0.000000e+000
-1.100000e+000=0xbf8ccccd:hex_to_float()=-1.100000e+000
-2.200000e+000=0xc00ccccd:hex_to_float()=-2.200000e+000
-3.300000e+000=0xc0533334:hex_to_float()=-3.300000e+000
-4.400000e+000=0xc08ccccd:hex_to_float()=-4.400000e+000
-5.500000e+000=0xc0b00000:hex_to_float()=-5.500000e+000
-6.600000e+000=0xc0d33333:hex_to_float()=-6.600000e+000
-7.700000e+000=0xc0f66666:hex_to_float()=-7.700000e+000
-8.800000e+000=0xc10ccccd:hex_to_float()=-8.800000e+000
-9.900001e+000=0xc11e6667:hex_to_float()=-9.900001e+000


-----------------------------------------------------------------------------

부동소수점 표현의 국제표준은 IEEE 754입니다.

-----------------------------------------------------------------------------

< float >
C의 float타입은 IEEE 754의 single precision 플로팅포인트를 구현한 것으로,
다음과 같은 포맷을 가집니다.
sign : bit31 (1비트)
exponent : bit30~bit23 (8비트)
mantissa : bit22~bit0 (23비트)

이때, 가수부(만티사)는 정수부분을 1로 정규화한 2진소수표현이며, 지수부(exponent)는
원래 지수에 바이어스 127을 더한 값입니다.
부호비트는 0이면 양수, 1이면 음수입니다.

가수부의 23비트가 100 0000 0000 0000 0000 0000 이라면, 이때 이 부동소수의 가수는
2진소수로 1.1이 되어, 10진법으로는 1 + 1/2 = 1.5가 됩니다.

지수부의 표현이 1000 0000 이라면, 이 값은 바이어스 127, 즉 111 1111이 더해진 수
이므로 실제 지수는 128 - 127 = 1이 됩니다.

따라서, 0 100 0000 100 0000 0000 0000 0000 0000 으로 표현되는 부동소수는
따라서, [0] [100 0000 0] [100 0000 0000 0000 0000 0000] 으로 표현되는 부동소수는
1.5 * 2^1 = 3.0 을 표현하게 됩니다.

single precision의 유효숫자는 가수의 비트길이 (정수부분 포함)24에 의해 결정되며,
2^24 은 약 10^7.2 이므로, 유효숫자는 약 7자리가 됩니다.

-----------------------------------------------------------------------------

< double >
C의 double타입은 IEEE 754의 double precision 플로팅포인트를 구현한 것으로,
다음과 같은 포맷을 가집니다.
sign : bit63 (1비트)
exponent : bit62~bit52 (11비트)
mantissa : bit51~bit0 (52비트)

이때, single precision과는 지수부의 바이어스가 1023이라는 것만 다르고, 나머지
표현방법은 동일합니다.

double precision의 유효숫자 역시 정수부분을 포함한 가수의 비트길이 53에 의해 결정되며,
2^53 은 약 10^15.9 이므로, 유효숫자는 약 약 15자리가 됩니다.

-----------------------------------------------------------------------------

< 예외 정의 >
1. 플로팅포인트 표현에서 모든 비트가 0인 수는 0으로 정의합니다.
2. 지수부의 모든 비트가 0인 수는 가수의 정수부분을 0으로 계산합니다.
3. 지수부의 모든 비트가 1이고, 가수부의 모든 비트가 0이면 무한대로 정의합니다.
4. 지수부의 모든 비트가 1이고, 가수부가 0이 아니면 NaN (Not a Number)로 정의하여
   예외를 발생하게 됩니다.


Posted by 셈말짓기 :