C06-基本数据在内存表现形式之浮点编码

double相关的浮点编码学习

与float 类似

               float                 	double
  存储长度	   4byte	                8byte
  存储位数	   32bit	                64bit
  符号位	   1	                    1
  指数位	   8                    	11
  有效位	   23                    	52

double的指数位 是 加上1023 占11位 其余都与float计算一样

构造一个unsigned int类型的数字,将它赋值给float类型后,会丢失数据

100000000000000001

反汇编IDA
exe到obj到c文件

以下代码会出现崩溃

int main()
{
char chValue=0;
scanf("%d",&chValue);
printf("%d",chValue);
return 0;
}

原因所在,char类型所占一个字节
scanf中%d是整型类型 所占4个字节 所以就会占其他本不属于自己的空间 栈破坏掉了
printf

int main()
{
 int nValue = 0xffffffff;
 unsigned uValue = 0xffffffff;
 printf("%d %d\r\n", nValue, uValue);
 printf("%u %u\r\n", nValue, uValue);
}

以上调试过程中
当nValue 与uValue存进去的时候 数据都是一样的 存入的都是0xffff ffff
只有当printf输出的时候 才会改变
在这里插入图片描述

printf会减慢运行速度 相当于单片机的IO口

void Myfun(unsigned uCount)
{
 for (size_t i = 0; i < uCount; i++)
 {
  printf("%d\r\n", i);
 }
}

int main()
{
 Myfun(-1);
}

以上的-1 会被强制转化为-1的16进制0xffffffff
就会很大 printf会处理
当时如果注释掉中间的printf
后面加上一个printf时间不会用的那么多

void Myfun(unsigned uCount)
{
 for (size_t i = 0; i < uCount; i++)
 {
  //printf("%d\r\n", i);
 }
printf(" Hello world!");
}

浮点编码

科学计数法

用科学计数法表示1234566.222 0.555666
1.234566222 ∗ 1 0 6 1.234566222*10^6 1.234566222106
5.55666 ∗ 1 0 − 1 5.55666*10^{-1} 5.55666101

十进制小数如何转换为二进制的小数

5.625对应的二进制为多少?
101.101
对于十进制的5.625,可以看作:
5 ∗ 1 0 1 + 6 ∗ 1 0 − 1 + 2 ∗ 1 0 − 2 + 5 ∗ 1 0 − 3 = 5.625 5*10^1+6*10^{-1}+2*10^{-2}+5*10^{-3}=5.625 5101+6101+2102+5103=5.625
101.101的二进制:
1 ∗ 2 2 + 1 ∗ 2 0 + 1 ∗ 2 − 1 + 1 ∗ 2 − 3 1*2^{2}+1*2^{0}+1*2^{-1}+1*2^{-3} 122+120+121+123
就是 1.01101 ∗ 2 2 1.01101*2^{2} 1.0110122

浮点编码方案及转化步骤

表达一个小数,从科学计数法,需要三个部分:

  • 符号
  • 有效数字
  • 指数
    以float为例 sizeof(float)=4,一共有32位,在float方案中,将32位划分以下三个部分:
  • 31bit:符号位 最高位,如果为1 表示为负数,否则表示为正数。
  • 中间的8bit:指数部分,可以为正指数,也可以是负指数。
  • 其余的23bit:有效数字部分,不足补0。
    进一步的解释,对于一个已经转为科学计数法的二进制浮点数

中间8bit表示指数,因为指数可以为正为负,所以编码规范中做了以下规定
将科学计数法中的指数部分,加上127后得到的结果,作为指数部分的数据。

有效数字位:二进制 只有0 1 但是科学计数法 必须为非零数值(所以必须为1),所以只需要记录小数部分

实例验证

转化为5.625,来得到计算机的16进制 验证
将上数字转化为二进制科学计数法
$ 1.01101*2^{2}$
符号位为 0
指数位为 2+127=129 1000 0001
有效数字位 01101

以上拼接起来就是 0 1000 0001 01101 000000000000000000
合起来 01000000101101000000000000000000
=>0100 0000 1011 0100 0000 0000 0000 0000
0x 40 B4 00 00

验证如下

在这里插入图片描述

面试题目

对于两个浮点型是否直接用==判断相等
答 不可以

int main()
{
 float fValue1 = 3.14f;
 float fValue2 = 3.0f;
 fValue2 += 0.1f;
 fValue2 += 0.04f;
 if (fValue1 == fValue2)
 {
  printf("相等\r\n");
 }
 else
 {
  printf("不相等\r\n");
 }
}

因为这关于3.14转为为机器16进制的时候 会出现无限取整数的情况 所以会产生小误差
解决方案如下
将两个数相减 然后差值小于一定范围就可

int main()
{
 float fValue1 = 3.14f;
 float fValue2 = 3.0f;
 fValue2 += 0.1f;
 fValue2 += 0.04f;
 if (fValue1-fValue2<0.0001&&
  fValue1-fValue2>-0.001)
 {
  printf("相等\r\n");
 }
 else
 {
  printf("不相等\r\n");
 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值