原问题见:

有1个c语音的源代码不清楚它为什么输出这个数,所以想请教一下?​www.zhihu.com

大概说一下问题,对于程序:

float a = 123456.789e5;
float b = a + 20;
printf("%fn", b);

将输出什么?是12345678920.000000 吗?

下面仅考虑 float 为使用 IEEE 754 32 位单精度浮点数的情况,

即 float 为 32 位,其中 1 为符号位,接下来,8 位阶码,最后,23 位尾码

任何一个浮点数(除 0 以外),都可以表示为:

V = (-1)^s * M * 2^E

  1. 当 (-1)^s 为 1 时,表示正数,为 -1 时,表示负数,在计算机内存储时,0 表示正数,1 表示负数
  2. M 表示尾码,范围为 [1, 2),可以写成 1.xxxxx 的形式,由于, 1 肯定存在,所以,在计算机内只存储小数部分
  3. E 表示阶码,阶码可正可负,在计算机内存储时,会将实际的阶码加一个偏移量存储,对于 32 为 float,偏移量为 127

接下来分析这个数:

123456.789e5

= 12345678900

= 8589934592 + 2147483648 + 1073741824 + 268435456 + 134217728 + 67108864 + 33554432 + 16777216 + 8388608 + 4194304 + 1048576 + 524288 + 262144 + 4096 + 2048 + 1024 + 32 + 16 + 4

= 2^33 + 2^31 + 2^30 +2^28 + 2^27 + 2^26 + 2^25+2^24+2^23 + 2^22 + 2^20 + 2^19 + 2^18 + 2^12+2^11 + 2^10 + 2^5 + 2^4 + 2^2

= 10 1101 1111 1101 1100 0001 1100 0011 0100(二进制)

= 1.0 1101 1111 1101 1100 0001 1100 0011 0100 * 2^33 (二进制)

此数大于 0,所以符号位部分存储为 0

此数,阶码为33,偏移量为 127,33 + 127 = 160 = 1010 0000,

阶码部分存储为 1010 0000

如上所述,对于 1.0 1101 1111 1101 1100 0001 1100 0011 0100,最前面的 1 不存储,只存储小数位,由于,尾码只有 23 为,而 1.0 1101 1111 1101 1100 0001 1100 0011 0100,小数部分有 33 位,所以只能忽略点最后 10 位,即,尾码部分为 011 0111 1111 0111 0000 0111(此处损失了精度

最后此数在计算机内表示为:0101 0000 0011 0111 1111 0111 0000 0111

将其转化为浮点数为:12345678848.000000,所以,float 类型的 123456.789e5 在计算机内表示为:12345678848.000000

接下来,在考虑 a + 20,int 和 float 相加,int 将先转换为 float

所以,20 = 2^4 + 2^2 = 1.01 * 2 ^ 4,即:

符号位表示为:0

阶码为 4,加上偏移量 127,4 + 127 = 131 = 1000 0011,阶码部分存储为 1000 0011

尾码,对于 1.01 不存储最前面的 1,阶码共 23 位 ,而小数部分只有两位,不足用 0 填,所以,尾码,存储为:010 0000 0000 0000 0000 0000

所以 float 类型的 20,存储为 0100 0001 1010 0000 0000 0000 0000 0000

现在,再考虑两数相加,

0101 0000 0011 0111 1111 0111 0000 0111(123456.789e5)

0100 0001 1010 0000 0000 0000 0000 0000(20)

首先,进行,阶码对齐,123456.789e5 的阶码为:1010 0000(160),20 的阶码为 1000 0011(130),

小阶码向大阶码对齐,所以,将 0100 0001 1010 0000 0000 0000 0000 0000(20)的阶码转化为 1010 0000 (160),将尾码(包括未存储的 1)向右移 30 位,空位用 0 填充, 即转换为 0101 0000 0(0)000 0000 0000 0000 0000 0000(此处有精度损失

现在:

0101 0000 0(1)011 0111 1111 0111 0000 0111(123456.789e5)

0101 0000 0(0)000 0000 0000 0000 0000 0000(20)

接下来,阶码不变,由于两数都是正数,所以尾码相加(需要加上尾码未存储的1),尾码部分结果为:(1)011 0111 1111 0111 0000 0111

然后,进行格式化,这个例子不需要格式化,(此步可能损失精度

所以,加上符号位和阶码,最终结果为:

0101 0000 0011 0111 1111 0111 0000 0111(12345678848.000000)

结论:浮点数,进行存储或运算时,可能会有精度损失

此外,还有几个特殊的浮点数:

  1. 符号位,指数部分,尾数部分都为 0,表示 0.0

0000 0000 0000 0000 0000 0000 0000 0000

2. 符号位为 1,指数部分,尾数部分都为 0,表示 -0.0

1000 0000 0000 0000 0000 0000 0000 0000

3. 符号位为 0,指数部分都为 1,尾数部分都为 0,表示正无穷大

0111 1111 1000 0000 0000 0000 0000 0000

4. 符号位为 1,指数部分都为 1,尾数部分都为 0,表示负无穷大

1111 1111 1000 0000 0000 0000 0000 0000

5. 符号位无所谓,指数部分都为 1,尾数部分为非 0,表示不是一个数字,是 NaN

*111 1111 1 + 非0

3 float py 位小数 裁剪_对一个 float 精度问题的分析相关推荐

  1. JAVA零碎要点015---java BigDecimal常见操作_加减乘除操作_比较_取几位小数四舍五入_随时更新

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 之前项目都很少用这个BigDecimal啊,最近这个项目对精度要求高,一个电视购物,广告拍摄,排挡 ...

  2. access两位小数不进位_人教版小学数学三年级下册笔算乘法(不进位)公开课优质课课件教案视频...

    人教版三年级下册数学<乘数是两位数的乘法>教学设计 教学目标 学生已经掌握了乘数是一位数的笔算法则,在此基础上,现在进一步学习乘数是两位数的乘法,对于计算法则,虽然只是个推广问题,但是要使 ...

  3. python 保留两位小数 占位_第17p,Python中格式化输出的3种方式

    大家好,我是杨数Tos,这是<从零基础到大神>系列课程的第17篇文章,第二阶段的课程:Python基础知识:格式化输出的3种方式 学习本课程,建议先看一遍:[计算机基础知识]课程. 格式化 ...

  4. php 随机两位小数数_使用8086微处理器找出两个8位N数数组

    php 随机两位小数数 Problem statement: 问题陈述: Write a program in 8086 microprocessor to find out the sum of t ...

  5. access两位小数不进位_文章列表-火龙的博客 - PHP,GO,MySQL知识分享问题记录博客...

    HTTP状态码HTTP Status Code明细 发布时间:2020-10-27 13:54:54   分类:其他 常见的状态码: – 服务器成功返回网页 – 请求的网页不存在 – 服务不可用详解: ...

  6. java保留两位小数四舍五入_关于java 四舍五入使java保留2位小数示例讲解

    关于java 四舍五入使java保留2位小数示例讲解 复制代码 代码如下: /* * 测试四舍五入 */ package com.icer.test; /** * * @author Hanbin * ...

  7. double取两位小数_Java语言中:float、double数据类型在内存中是如何存储的

    java语言中,float类型数字在计算机中用4个字节(32位)来存储.double类型占用8个字节(64位). 从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float ...

  8. 三位整数两位小数掩码_小数点造句_造句大全

    小数点造句: 1.怪圈中心近处的那个小圆圈,就是小数点. 2.这个参数可与一个数字联合使用,以告知格式化程序有多少个小数点要使用. 3.由于我预想到此商家会遗漏金额的小数点和方法,因此脚本在需要的时候 ...

  9. access两位小数不进位_【2017年最新】☞ iOS面试题及答案

    设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的事情. 1). MVC模式:Model View Control,把模型 视图 控制器 ...

最新文章

  1. c js html页面进度条,js实现进度条的方法
  2. [转]《JAVA与模式》之责任链模式
  3. 关于python3的标识符_python3中关于基础语法的详解
  4. 【推荐】大型网站图片服务器架构的演进
  5. 你的iOS静态库该减肥了
  6. MoreResult 同事返回多个数据集
  7. CentOS 7 最小化安装简单配置
  8. oracle exp执行失败,EXP-00056: 遇到 ORACLE 错误 25153
  9. poj1833 排列
  10. 为 iOS 6 量身打造 Apps
  11. centos7安装mysql允许远程连接_Centos7安装mysql8.0,开启远程访问
  12. 高等代数-三-消元法
  13. 火狐浏览器将网页保存为pdf
  14. 换号码的烦恼引起的思考
  15. windows和linux下编译draco
  16. halcon入门之_提取遥控器字符并且写入txt文本
  17. 零界之痕服务器维护,《零界之痕》1月26日更新维护公告
  18. Android接入极光消息推送
  19. AD19——1:1打印PCB原理图(查看封装是否适合实际器件)
  20. 搭建自己的小程序服务器

热门文章

  1. 20211018 一些特殊矩阵
  2. 2020-10-13 多智能体基本图论
  3. Quartz.Net进阶之四:CronTrigger 详述
  4. 小甲鱼-010-012列表
  5. 分享cropper剪切单张图片demo
  6. HDU2855—Fibonacci Check-up
  7. Centos之帮助命令
  8. 02 - Unit06:弹出对话框
  9. YTU 2586: 填空题B-字画鉴别
  10. C语言实现-双链表练习