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;
}

Last updated