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)[];
} 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 - ;
if(is_little_endian())
{
for(i=max_i; i>=; i--)
{
for(j=; j>=; j--)
{
printf("%d", ((pos[i] & ( << j)) ? : ));
if (j == || j == )
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 ;
}

然后就是我的学习时间了

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 = ;
int tmp; int count = ;
int highPos = -;
int lowPos = -;
int flag = ; printf(" Input : ");
scanf("%d" , &num); int i = ;
/*******************核心代码*********************/
while(i != )
{
tmp = num&(<<i);
if(tmp)
{
highPos = i;
count++;
if(flag)
{
lowPos = i;
flag = ;
}
}
i++;
}
/************************************************/
printf(" NUMBER: %d\n" , num);
printf(" BITS: %d\n" , count);
if(count >= )
{//如果有1
printf("HIGHEST 1: %d\n" , highPos);
printf(" LOWEST 1: %d\n" , lowPos);
}
else
{//没有1
printf("HIGHEST 1: \n");
printf(" LOWEST 1: \n");
} return ;
}

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)[];
} //访问对象地址,访问对象大小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 - ;
if(is_little_endian())
{//此程序只适用小端模式,因为是根据指针访问存储数据
for(i=max_i; i>=; i--)
{
for(j=; j>=; j--)
{
bit= ((pos[i] & ( << j)) ? : );
printf("%d", bit);
/************************************/
if(bit == )
{//如果是1
if(highFlag == )
{
highFlag = ;
highPos = posHex;
}
lowPos = posHex;
count++;
}
posHex--;
/************************************/
if (j == || j == )
printf(" ");
}
printf(" ");
}
}
printf("\n");
} int main(int argc , char *argv[])
{
float num = ; /*************参数初始化************/
count = ;
posHex = ; highPos = -;
lowPos = -; highFlag = ;
lowFlag = ; /***********************************/
printf(" Input : ");
scanf("%f" , &num); /***********************************/
printf(" NUMBER: ");
print_float(&num); printf(" BITS: %d\n" , count);
if(count >= )
{//如果有1
printf("HIGHEST 1: %d\n" , highPos);
printf(" LOWEST 1: %d\n" , lowPos);
}
else
{//没有1
printf("HIGHEST 1: \n");
printf(" LOWEST 1: \n");
} return ;
}

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

__c语言__整型、实型的存储(十进制转二进制)的更多相关文章

  1. __c语言__结构体、共用体、枚举__笔记

    2017-09-16 21:14:09 结构体,共用体,枚举 1.结构体 把不同的类型整合成一个有机的整体,以便于引用,这个类型就叫做结构体 1)结构体变量的定义方式(3种)和引用成员变量: 定义一个 ...

  2. __c语言__测一段代码的运行时间

    2017-09-16 13:35:56 感觉很实用. /************************************** time ./a.out 命令所花费的real时间.user时间和 ...

  3. C语言的整型溢出问题

    整型溢出有点老生常谈了,bla, bla, bla… 但似乎没有引起多少人的重视.整型溢出会有可能导致缓冲区溢出,缓冲区溢出会导致各种黑客攻击,比如最近OpenSSL的heartbleed事件,就是一 ...

  4. c读入实型

    读入: 如果读入的数为整型,然后转为实型,则%lf 否则%f也可以 读出: %f,这样在codeblocks才能看到正确的结果

  5. Python基本数据类型之整型和布尔型

    整型和布尔型 获取对象的数据类型 1.type() 2.dir() 3.help() 4.在pycharm里面的操作 数字类型 int 创建: int() 接收数字字符串 .bit_lenght() ...

  6. SQLLite 可以通过SQL语言来访问的文件型SQL数据库

    Web Storage分为两类: - sessionStorage:数据保存在session 对象中(临时) - localStorage:数据保存在本地硬件设备中(永久) sessionStorag ...

  7. float:浮点型double:双精度实型decimal:数字型单精度浮点数(Single)双精度浮点数(double)

        单精度浮点数(Single) 双精度浮点数(double)       Decimal为SQL Server.MySql等数据库的一种数据类型,不属于浮点数类型,可以在定义时划定整数部分以及小 ...

  8. C++数据类型之实型(浮点型)&科学计数法

    实型(浮点型) **作用**:用于==表示小数== 浮点型变量分为两种: 1. 单精度float 2. 双精度double 两者的**区别**在于表示的有效数字范围不同. float类型数据,需在数据 ...

  9. 实型(浮点型):float、double

    实型(浮点型):float.double 实型变量也可以称为浮点型,浮点型变量是用来存储小数数值的.在C语言中,浮点型分为两种:单精度浮点型(float).双精度浮点型(double),但是doubl ...

随机推荐

  1. react native初始化项目

    打开命令行窗口,进入我们想要创建项目的父目录,输入命令: npm install -g yarn react-native-cli react-native init 项目名 进入新建的项目目录,执行 ...

  2. 再理解tcp backlog

    在Linux 2.2以前,backlog大小包括了半连接状态和全连接状态两种队列大小.linux 2.2以后,分离为两个backlog来分别限制半连接SYN_RCVD状态的未完成连接队列大小跟全连接E ...

  3. sendfile

    Sendfile 函数在两个文件描写叙述符之间直接传递数据(全然在内核中操作,传送),从而避免了内核缓冲区数据和用户缓冲区数据之间的拷贝,操作效率非常高,被称之为零拷贝. Sendfile 函数的定义 ...

  4. Jenkins的介绍

    在公司看见有的部门在使用这个工具,好奇一下,今天就开始学习一番. 1.官网 https://jenkins.io/ 2.介绍 Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用 ...

  5. linux文件打包并发送到其他服务器

    scp /data/backup/mongodump/mongodb.$DATE.tar root@192.168.1.70:/home/iscsi/mongodb/

  6. Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  7. Lunch War with the Donkey CSU - 2084

    Jingze is a big figure in California State University for his stubbornness. Because of his new failu ...

  8. 001.Kubernetes简介

    一 Kubernetes概述 Kubernetes是一个全新的基于容器技术的分布式架构领先方案.Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg).在Docker ...

  9. JDK 1.6 HashMap 源码分析

    前言 ​ 前段时间研究了一下JDK 1.6 的 HashMap 源码,把部份重要的方法分析一下,当然HashMap中还有一些值得研究得就交给读者了,如有不正确之处还望留言指正. 准备 ​ 需要熟悉数组 ...

  10. 湖南大学第十四届ACM程序设计新生杯(重现赛)

    RANK  0 题数 0 期末复习没有参加,补几道喜欢的题. A: AFei Loves Magic  签到 思路 :不需考虑 碰撞 直接计算最终状态即可. #include<bits/stdc ...