IEEE 754 and float 範例程式

功能:互轉浮點數與二進制表示法

/* ieee754.c

* Author: Aaron Liao (http://applezulab.netdpi.net)

* Last updated: 2010/12/29

* IEEE754 sample code

* LICENSE: GPL

* 32 bits: [1][8][23]

* 64 bits: [1][11][52]

*/

#include <strings.h>

#include <string.h>

#include <stdio.h>

int ieee754(char *data, double real)

{

int exp=0, i=0, exp_tmp;

double cal, frag_tmp;

char buf[32];

bzero(buf, sizeof(buf));

cal = real;

/* get sign */

if( cal < 0 ){

buf[0] = 1;

cal *= (double) -1;

} else {

buf[0] = 0;

}

/* get exp */

while( cal >= 1.0 ) {

cal /= 2;

exp++;

}

for( i=8, exp_tmp=1; i>0; i--){

if( (exp & exp_tmp) ) {

buf[i] = 1;

} else {

buf[i] = 0;

}

exp_tmp *=2 ;

}

/* get fraction */

for(i=9, frag_tmp = (double) 1/2; i< 32; i++) {

if( (cal - frag_tmp) >= 0 ){

buf[i] = 1;

cal = (double) cal - (double) frag_tmp;

} else {

buf[i] = 0;

}

frag_tmp /= (double) 2;

}

/* To ascii */

for(i=0; i<32; i++) {

buf[i] += '0';

}

strncpy(data, buf, 32);

return 0;

}

double rev_ieee754(char *buf)

{

int exp=0, i=0, exp_tmp, sign;

double real, frag_tmp;

int len = 32;

/* get sign */

if( buf[0] == '1' ){

sign = -1;

} else {

sign = 1;

}

/* get exp */

for( exp=0, i=8, exp_tmp=1; i>0; i--){

if( buf[i] == '1') {

exp += exp_tmp;

}

exp_tmp*=2;

}

/* get fraction */

for(i=9, real=(double)0, frag_tmp = (double) 1/2; i< len; i++) {

if( buf[i] == '1') {

real += frag_tmp;

}

frag_tmp /= (double) 2;

}

while(exp>0) {

real *= 2;

exp--;

}

real *= (double) sign;

return real;

}

int ieee754_64(char *data, double real)

{

int exp=0, i=0, exp_tmp;

double cal, frag_tmp;

static char buf[64];

bzero(buf, sizeof(buf));

cal = real;

/* get sign */

if( cal < 0 ){

cal *= (double) -1;

buf[0] = 1;

} else {

buf[0] = 0;

}

/* get exp */

while( cal >= 1.0 ) {

cal /= 2;

exp++;

}

for( i=11, exp_tmp=1; i>0; i--){

if( (exp & exp_tmp) ) {

buf[i] = 1;

} else {

buf[i] = 0;

}

exp_tmp *=2 ;

}

/* get fraction */

for(i=12, frag_tmp = (double) 1/2; i< 64; i++) {

if( (cal - frag_tmp) >= 0 ){

buf[i] = 1;

cal = (double) cal - (double) frag_tmp;

} else {

buf[i] = 0;

}

frag_tmp /= (double) 2;

}

/* To ascii */

for(i=0; i<64; i++) {

buf[i] += '0';

}

strncpy(data, buf, 64);

return 0;

}

double rev_ieee754_64(char *buf)

{

int exp=0, i=0, exp_tmp, sign;

double real, frag_tmp;

int len=64;

/* get sign */

if( buf[0] == '1' ){

sign = -1;

} else {

sign = 1;

}

/* get exp */

for( exp=0, i=11, exp_tmp=1; i>0; i--){

if( buf[i] == '1') {

exp += exp_tmp;

}

exp_tmp*=2;

}

/* get fraction */

for(i=12, real=(double)0, frag_tmp = (double) 1/2; i< len; i++) {

if( buf[i] == '1') {

real += frag_tmp;

}

frag_tmp /= (double) 2;

}

while(exp>0) {

real *= 2;

exp--;

}

real *= (double) sign;

return real;

}

/* test */

int main(void)

{

int i, j;

char buf[32], buf2[64];

for(i=1; i<=1000000; i*=2) {

bzero(buf, sizeof(buf));

bzero(buf2, sizeof(buf2));

ieee754( (char*)buf, (double) i);

printf("[32bit] %20f ->\t", rev_ieee754( (char*)buf));;

for(j=0; j<sizeof(buf); j++) {

printf("%c ", buf[j]);

}

printf("\n");

ieee754_64( buf2, (double) i);

printf("[64bit] %20f ->\t", rev_ieee754_64( (char*)buf2));;

for(j=0; j<sizeof(buf2);j++) {

printf("%c ", buf2[j]);

}

printf("\n");

}

return 0;

}