__c语言__整型、实型的存储(十进制转二进制)

float 和 double 类型数据在内存中的存储方法

  • 无符号整型采用32位编码,带符号整型数采用1个符号位31位底数编码;
  • 单精度数据采用了1位符号位,8位阶码,23位尾数的编码;
  • 双精度数据采用了1位符号位,10位阶码,52位尾数的编码;

 

  • 无符号整型的范围:0~2的32次方
  • 带符号整型:-2的31次方~2的31次方

 

  • 单精度规定用 8 位二进制表示阶数,即最大表示为 2 的 128 次方,把这个数算出来是 3.4028236692093846346337460743177e+38
  • 双精度规定用 11 位二进制表示阶数,即最大表示为 2 的 1024 次方,结果是 1.797693134862315907729305190789e+308

 

  • 浮点数(单精度的 float 和双精度的 double)在内存中以二进制的科学计数法表示,表达式为 N = 2^E * F;

其中E为阶码(采用移位存储),F 为尾数。

 

  • float 和 double 都由符号位阶码尾数三部分组成,float 存储时使用 4 个字节double 存储时使用 8 个字节

各部分占用位宽如下所示:

             符号位     阶码      尾数     长度

float              1           8         23      32

double          1         11        52      64

符号位:0代表正数,1代表负数。

阶码:用移位表示法存储科学计数法中的指数数据

float阶码占8位,取值范围-128~127,但并没有按照移位表示法+128,而是+127。

同理double要+1023。阶码也是指数位

尾数:用二进制的科学计数法表示后,去掉小数点前面恒定的1,只保留小数点后面的二进制数据,存入尾数位置即可。 

 

  • 比如8.25,二进制科学计数法表示为:1.00001*2^3,

具体转换方法:

8的二进制1000;

.25的二进制.01:即0*2^(-1) + 1*2^(-2)。

写为:1000.01,小数点左移3位,即转换完毕。

符号位确定:8.25为正数,符号位为0。

阶码的表示:阶码位3+127=130;二进制10000010,已经是8位。

尾数的表示:去掉小数点前面的1,为00001,后面补充0至23位:000 0100 0000 0000 0000 0000

最终8.25在内存里存储的二进制为:0100 0001  0000 0100  0000 0000  0000 0000

 

  • 又比如11.4,二进制科学计数法表示:

float:1.01101100110011001100110 * 2^3

double:1.0110  1100 1100  1100 1100  1100 1100  1100 1100  1100 1100  1100 1101 * 2^3

所以他们的值其实是不同的,因为.4用二进制无法精确表示

——这也就是为什么 float 类型数据 和 double 类型数据 都存储11.4,但是对比起来,他们不相等的原因。

比如 float a = 11.4; double b = 11.4; 要让他们正确对比,((float)b == a),让 double 数据舍弃比 float 多的那些尾数。

 

  • 对于 double 型数据,只要将阶码前面加0扩展到11位,尾数后面补充0至52位即可。

 

移位表示法

在数 X 上加一个偏移量,常用于表示浮点数中的阶码(注意阶码的偏移量和移位表示法定义有差别)。

定义:

若 X为纯整数,X[移] = 2^(n-1) + X,-2^(n-1) <= X < 2^(n-1);

若X为纯小数,X[移] = 1 - X,-1<= X < 1

下面这个代码,我很喜欢,其中有很多思想,对我来说很有用,膜拜下某大神

#include <stdio.h>  
  
#define print_float(a) print_bitxx(a, 4)  
#define print_int(a) print_bitxx(a, 4)  
  
#define print_double(a) print_bitxx(a, 8)  
  
int is_little_endian()  
{  
    short int x = 0x0001;  
    return ((char*)&x)[0];  
}  
  
void print_bitxx(const void *a, int bytes)  
{  
    const unsigned char *pos = (const unsigned char *)a;  
    int i, j;  
    int max_i;
    max_i = bytes - 1;
    if(is_little_endian())
    {  
        for(i=max_i; i>=0; i--)
        {  
            for(j=7; j>=0; j--)
            {  
                printf("%d", ((pos[i] & (1 << j)) ? 1 : 0));  
                if (j == 4 || j == 0)  
                    printf(" ");  
            }  
            printf(" ");  
        }  
    }  
    printf("\n");  
}  
  
int main(int argc, char **argv)  
{
    int a = 8.25;
    float b = 8.25;  
    double c = 8.25;
    
    print_int(&a);  
    print_float(&b);  
    print_double(&c);  
    printf("%d\n", b == (float) c);  
    printf("%d\n", (double)b == (double) c);  
    return 0;  
}  

 

然后就是我的学习时间了

1、编写程序把一个整型二进制数中 1 的个数,最高位1的位置和最低位1的位置显示出来。

程序接受用户输入的一个整数(分别正数一个,负数一个)

输出该整数,以及其中 1 的个数最高位 1 的位置最低位 1 的位置

用GCC编译程序运行,检查程序运行是否正确。

/*编写程序
    把一个整型二进制数中1的个数,最高位1的位置和最低位1的位置显示出来。
    程序接受用户输入的一个整数(分别正数一个,负数一个),
    输出该整数,
    以及其中1的个数,
    最高位1的位置,
    最低位1的位置。
    
    一个示例的输出如下
           NUMBER: 2049
             BITS: 2
        HIGHEST 1: 11
         LOWEST 1: 0
    据实验:输入的数字范围是(-2^31) 到 (2^31 - 1) 
                            -2147483648 到 2147483647
    本代码移位运算测试,int 和unsigned int无区别
*/
#include <stdio.h>

int main(int argc , char *argv[])
{
    int num = 0;
    int tmp;
    
    int count = 0;
    int highPos = -1;
    int lowPos = -1;
    int flag = 1;
    
    
    printf("   Input : ");
    scanf("%d" , &num);
    
    int i = 0;
/*******************核心代码*********************/
    while(i != 32 )
    {
        tmp = num&(1<<i); 
        if(tmp)
        {
            highPos = i;
            count++;
            if(flag)
            {
                lowPos = i;
                flag = 0;
            }
        }
        i++;
    }
/************************************************/    
    printf("   NUMBER: %d\n" , num);
    printf("     BITS: %d\n" , count);
    if(count >= 1)
    {//如果有1
        printf("HIGHEST 1: %d\n" , highPos);
        printf(" LOWEST 1: %d\n" , lowPos);
    }
    else
    {//没有1
        printf("HIGHEST 1: \n");
        printf(" LOWEST 1: \n");
    }
    
    return 0;
}

 

2、编写程序把一个实型二进制数中 1 的个数,最高位 1 的位置 和 最低位 1 的位置 显示出来。

程序接受用户输入的一个整数(分别正数一个,负数一个)

输出该整数,以及其中1的个数,最高位1的位置,最低位1的位置。

用GCC编译程序运行,检查程序运行是否正确。

/*编写程序
    把一个实型二进制数中1的个数,最高位1的位置和最低位1的位置显示出来。
    程序接受用户输入的一个实型(分别正数一个,负数一个),
    输出该实型,
    以及其中1的个数,
    最高位1的位置,
    最低位1的位置。
    
    root@kjf:/mnt/hgfs/workPlace/01_computer/20170914# ./a.out 
           Input : 8.25
           NUMBER: 0100 0001  0000 0100  0000 0000  0000 0000  
             BITS: 3
        HIGHEST 1: 30
         LOWEST 1: 18
*/
#include <stdio.h>

#define print_float(a) print_bitxx(a, 4)        //访问对象地址,访问对象大小float为4字节

int count;
int posHex;

int highPos;
int lowPos;

int highFlag;
int lowFlag;

//判断小端模式
int is_little_endian()        
{  
    short int x = 0x0001;  
    return ((char*)&x)[0];  
}

//访问对象地址,访问对象大小float为4字节。。。打印存储的二进制数
void print_bitxx(const void *a, int bytes)
{
    int bit;
    const unsigned char *pos = (const unsigned char *)a;  
    int i, j;  
    int max_i;
    max_i = bytes - 1;
    if(is_little_endian())
    {//此程序只适用小端模式,因为是根据指针访问存储数据
        for(i=max_i; i>=0; i--)
        {  
            for(j=7; j>=0; j--)
            {  
                bit= ((pos[i] & (1 << j)) ? 1 : 0);
                printf("%d", bit);
                /************************************/
                if(bit == 1)
                {//如果是1
                    if(highFlag == 0)
                    {
                        highFlag = 1;
                        highPos = posHex;
                    }
                    lowPos = posHex;
                    count++;
                }
                posHex--;
                /************************************/
                if (j == 4 || j == 0)  
                    printf(" ");  
            }  
            printf(" ");  
        }  
    }  
    printf("\n");  
}

int main(int argc , char *argv[])
{
    float num = 0;
    
    /*************参数初始化************/
    count = 0;
    posHex = 31;
    
    highPos = -1;
    lowPos = -1;
    
    highFlag = 0;
    lowFlag = 0;
    
    /***********************************/
    printf("   Input : ");
    scanf("%f" , &num);
    
    /***********************************/
    printf("   NUMBER: ");
    print_float(&num);
    
    printf("     BITS: %d\n" , count);
    if(count >= 1)
    {//如果有1
        printf("HIGHEST 1: %d\n" , highPos);
        printf(" LOWEST 1: %d\n" , lowPos);
    }
    else
    {//没有1
        printf("HIGHEST 1: \n");
        printf(" LOWEST 1: \n");
    }
    
    return 0;
}

 http://canlynet.iteye.com/blog/1796889

posted @ 2017-09-16 14:25  耶梦加德  阅读(1943)  评论(0编辑  收藏  举报