由(int&)a引发的思考及浮点数在内存中的表示

本文解析了一段涉及浮点数操作的C++代码,详细解释了(float)和(double)类型的内部存储格式及其转换过程,展示了如何理解(float)1.0f和0.0f在内存中的表示。

今天看到一段代码,如下:请写出它的输出结果

 

看到这段代码,一些概念性的东西一下就搞混了,(int&)a是什么含义呢?让我来看看输出结果:

0013FF60
1310560
1065353216
false
0
0
true

 

(int)&a 把a的地址强制转换成整型

(int&)a 把a强制转换成整形引用类型,相当于是某个整形引用,引向了a所在的32位内存区域,并将这32位当做一个整数。

(int)a a在内存中的值转换成int类型

   对于浮点数1.0,根据IEEE754的浮点数存储格式表示为3f800000(0011 1111 1000 0000 0000 0000 0000 0000),(int&)a把3f800000当做int型输出,所以结果为1065353216。

这里对float和double存储格式介绍一下:

C/C++的浮点数据类型有float和double两种。
 
类型float大小为4字节,即32位,内存中的存储方式如下:
高地址<-------------------------------------->低地址
|  符号位  |     指数   |          尾数          |
|  1 bit   |    8 bit   |         23 bit         |
31<------>30<--------->22<---------------------->0

类型double大小为8字节,即64位,内存布局如下:
高地址<---------------------------------------->低地址
|  符号位  |      指数    |          尾数          |
|   1 bit  |     11 bit   |         52 bit         |
63<------>62<------------>51<--------------------->0

 
符号位决定浮点数的正负,0表示正,1表示负。
指数和尾数均从浮点数的二进制科学计数形式中获取。
如,十进制浮点数2.5的二进制形式为10.1,转换为科学计数法形式为(1.01)*(21),由此可知指数为1,尾数(即科学计数法的小数部分)为01。
根据浮点数的存储标准(IEEE制定),float类型指数的起始数为127(二进制0111 1111),double类型指数的起始数为1023(二进制011 1111 1111),在此基础上加指数,得到的就是内存中指数的表示形式。尾数则直接填入,如果空间多余则以0补齐,如果空间不够则0舍1入。所以float和double类型分别表示的2.5如下(二进制):
float
|符号位|    指数   |            尾数
|   0  | 1000 0000 | 010 0000 0000 0000 0000 0000
double
|符号位|      指数     |                 尾数
|   0  | 100 0000 0000 | 0100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

浮点数2.5可以用二进制小数准确表示(2.5=1*(21)+0*(20)+1*(2-1)),但很多小数不可以准确表示,其二进制形式的小数部分会无限循环,如浮点数-1.2表示如下(二进制):
float
|符号位|    指数   |            尾数       
|   1  | 0111 1111 |  0011 0011 0011 0011 0011 010 
double
|符号位|       指数    |                 尾数
|   1  | 011 1111 1111 | 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011

    由于对无限循环尾数的截取遵循0舍1入,尾数的第21~24位为0011,第53~56位为0011,而float尾数容量为23位,double尾数容量为52位,所以,float形式的最后三位因进位而成010,double形式则没有进位发生。
    类型float和double通过==,>,<等比较不会引起编译错误,但是非常可能得到错误的结果。这是因为它们的内存分布不同,不可以直接比较。正确的方法是转换为同一类型后比较两者差值,如果结果小于规定的小值,则视为相等。

ps:
1) IEEE浮点数标准:  
4字节浮点数:1位符号位,8位阶数(基数为127的移码),23位尾数;
8字节浮点数:1位符号位,11位阶数(基数为1023的移码),52位尾数

2 ) 在VC中: float数值范围约在 -10e38~10e38,并提供7位有效数字位,绝对值小于10e38地数被处理成零值 double数值范围约在-10e308~10e308,并提供15~16位有效数字,绝对值小于10e308地数被处理成零值

任务描述 本关任务:程序输入苹果数 m 和人数 n,要求输出每个人平均可以分到多少个苹果,并将计算结果存入到变量 x 中。 相关知识 C 的程序中,每个数据对象都必须有确定的数据类型。这是为什么呢?我们知道,计算机内存中的数据都是0、1串,例如下面这16位0、1组成的串。 01000001 01000010 那么这个0、1串到底代表什么意思呢? 同样的这一段0、1串,如果是8位整数,则是两个整数65和66;如果是字符,则是&lsquo;A&rsquo;和&lsquo;B&rsquo;;如果是16位整数,则是16706。 同一串数据,赋予不同的类型就有不同的解释,就代表了不同的含义,所以数据对象都必须有确定的数据类型。C 有四种基本数据类型:整型、浮点型、字符型和布尔型。 本关我们首先来介绍整形和浮点型。 整型 C 的整型数据分为有符号和无符号两类,每类又包含几种类型。不同的 C 编译器对同一种数据类型的表示方式可能会有不同。 典型的 C 整型类型如下表: 类别 类型名 简写 名称 存储长度 表示范围 有符号 signed short int Short 有符号短整型 2 字节 -32768~32767 有符号 signed int Int 有符号整型 4 字节 -2147483648~2147483647 有符号 signed long int Long 有符号长整型 4 字节 -2147483648~2147483647 无符号 unsigned short int unsigned short 无符号短整型 2 字节 0~65535 无符号 unsigned int unsigned 无符号整型 4 字节 0~4294967295 无符号 unsigned long int unsigned long 无符号长整型 4 字节 0~4294967295 整型数据可以参与算术运算、关系运算、逻辑运算、位运算等。整数的加法、减法、乘法和数学中的算术运算一致,而除法略有不同。 例如: int a = 23, b = 8, c; // 声明整型变量 a、b、c,并对 a、b 进行初始化 c = a / b; // 计算 a 除以 b 并将结果存入 c 中 printf(&quot;%d\n&quot;,c); // 输出 c 的值 输出结果为:2 说明:23/8的结果为2,而不是2.875。这是因为两个整数相除,采用的是整数除法,结果也是整数。而且不是四舍五入的整数,而是直接截掉小数部分的整数。 浮点型 具有浮点型的数叫浮点数,也常常被称为双精度数或实数。如果要得到除法结果的小数部分,需要使用浮点数除法。只要除数和被除数其中有一个是浮点数,系统就会使用浮点数除法。 例如: float num = 123 / 23.0; printf(&quot;%f\n&quot;,num); 输出结果为:5.347826 说明:算式中23.0为浮点数,所以123/23.0采用浮点数除法,结果也是浮点数(存入到浮点变量 num 中)。使用 printf 输出时,采用的转换说明符也是相应的%f。 编程要求 在右侧编辑器中的Begin-End之间补充代码,要求计算每个人平均分得的苹果数。具体要求如下: 程序输入苹果总数 m 和总人数 n(数据将由平台提供,m 和 n 之间用一个空格隔开,需要你获取即可使用); 以&ldquo;人均苹果数为:num&rdquo;的格式输出,其中 num 即每个人平均分得的苹果数。 测试说明 平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试: 测试输入:23 5 预期输出:人均苹果数为:4 测试输入:100 34 预期输出:人均苹果数为:2 思考:想一想,34 人分 100 个苹果,每人才 2 个,剩下的苹果哪儿去了? 任务描述 本关任务:程序输入苹果数 m 和人数 n,要求输出每个人平均可以分到多少个苹果,并将计算结果存入到变量 x 中。 相关知识 C 的程序中,每个数据对象都必须有确定的数据类型。这是为什么呢?我们知道,计算机内存中的数据都是0、1串,例如下面这16位0、1组成的串。 01000001 01000010 那么这个0、1串到底代表什么意思呢? 同样的这一段0、1串,如果是8位整数,则是两个整数65和66;如果是字符,则是&lsquo;A&rsquo;和&lsquo;B&rsquo;;如果是16位整数,则是16706。 同一串数据,赋予不同的类型就有不同的解释,就代表了不同的含义,所以数据对象都必须有确定的数据类型。C 有四种基本数据类型:整型、浮点型、字符型和布尔型。 本关我们首先来介绍整形和浮点型。 整型 C 的整型数据分为有符号和无符号两类,每类又包含几种类型。不同的 C 编译器对同一种数据类型的表示方式可能会有不同。 典型的 C 整型类型如下表: 类别 类型名 简写 名称 存储长度 表示范围 有符号 signed short int Short 有符号短整型 2 字节 -32768~32767 有符号 signed int Int 有符号整型 4 字节 -2147483648~2147483647 有符号 signed long int Long 有符号长整型 4 字节 -2147483648~2147483647 无符号 unsigned short int unsigned short 无符号短整型 2 字节 0~65535 无符号 unsigned int unsigned 无符号整型 4 字节 0~4294967295 无符号 unsigned long int unsigned long 无符号长整型 4 字节 0~4294967295 整型数据可以参与算术运算、关系运算、逻辑运算、位运算等。整数的加法、减法、乘法和数学中的算术运算一致,而除法略有不同。 例如: int a = 23, b = 8, c; // 声明整型变量 a、b、c,并对 a、b 进行初始化 c = a / b; // 计算 a 除以 b 并将结果存入 c 中 printf(&quot;%d\n&quot;,c); // 输出 c 的值 输出结果为:2 说明:23/8的结果为2,而不是2.875。这是因为两个整数相除,采用的是整数除法,结果也是整数。而且不是四舍五入的整数,而是直接截掉小数部分的整数。 浮点型 具有浮点型的数叫浮点数,也常常被称为双精度数或实数。如果要得到除法结果的小数部分,需要使用浮点数除法。只要除数和被除数其中有一个是浮点数,系统就会使用浮点数除法。 例如: float num = 123 / 23.0; printf(&quot;%f\n&quot;,num); 输出结果为:5.347826 说明:算式中23.0为浮点数,所以123/23.0采用浮点数除法,结果也是浮点数(存入到浮点变量 num 中)。使用 printf 输出时,采用的转换说明符也是相应的%f。 编程要求 在右侧编辑器中的Begin-End之间补充代码,要求计算每个人平均分得的苹果数。具体要求如下: 程序输入苹果总数 m 和总人数 n(数据将由平台提供,m 和 n 之间用一个空格隔开,需要你获取即可使用); 以&ldquo;人均苹果数为:num&rdquo;的格式输出,其中 num 即每个人平均分得的苹果数。 测试说明 平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试: 测试输入:23 5 预期输出:人均苹果数为:4 测试输入:100 34 预期输出:人均苹果数为:2 思考:想一想,34 人分 100 个苹果,每人才 2 个,剩下的苹果哪儿去了?
07-04
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值