1. 问题

为什么1e38f + 1 - 1e38f为0?

2. 分析

    int ii = ; //00 00 00 02

    int *pii = ⅈ

    float i = 1e38f; //7e 96 76 99     (0111 1110  1001 0110  0111 0110  1001 1001)

    float j = -1e38f;//fe 9676 99      (1111 1110  1001 0110  0111 0110  1001 1001)

    float *pi = &i;

    float *pj = &j;

    int fs = sizeof(float);

    float k = i + j + ; //3f 80 00 00  (0011 1111 1000 0000 0000 0000 0000 0000)
float l = i + + j; //00 00 00 00 float *pk = &k;
float *pl = &l;

根据IEEE 754single-precision binary floating-point format

单精度浮点数:4个字节,最高位为符号位,23-30共8位指数,0-22共23为尾数(隐藏了最高位1);指数用移码表示,指数的偏移量为127;尾数用补码表示。

float i = 1e38f; //99 76 96 7e  (0111 1110  1001 0110  0111 0110  1001 1001)

符号位:0

指数:1111 1101

尾数:001 0110  0111 0110  1001 1001

float j = -1e38f; //99 76 96 fe (1111 1110  1001 0110  0111 0110  1001 1001)

符号位:1

指数:1111 1101(和上面一样有没有)

尾数:001 0110  0111 0110  1001 1001

指数对齐,尾数相加,(对齐时,指数向大的对齐,相加前小的指数对应的尾数要右移指数差位)

这里指数一样大,不用对齐;

1 = +1 * 2^0

符号位:0

指数:127(0111 1111)

尾数:1(000 0000 0000 0000 0000 0000)

0 0111 1111 000 0000 0000 0000 0000 0000

3.  i + 1计算步骤:

3.1 指数对齐

1111 1101和0111 1111,差为253-127=126

尾数相加时要把隐藏的1写出来;

尾数补上最高位1,再右移126位,由于右移126位超过了23位,尾数都被移除,全被置0。

3.2 尾数相加

1001 0110  0111 0110  1001 1001

+  0000 0000  0000 0000  0000 0000

= 0 1001 0110  0111 0110  1001 1001

3.3 溢出判断

上面的数没有溢出;

如果溢出将该数右移1位且指数加1

3.4 结果合成

由于尾数实际为24位,最高位总为1,实际上只存储23位,最高位不存储。

去除尾数最高位及指数部分清0:result =result &(~0xFF800000)

和较大指数合并:result= result| (e1 << 23);

result即为浮点数的二进制表示了,把它转换成浮点数:c = *((float *)&result);

由上述可以得出,尾数相加后不变,指数不变,所以和结果不变,仍为较大的那个浮点数。

进而我们可以得出一个结论:当两个浮点数的指数相差超过浮点数的尾数位数,那么两个浮点数的相加结果将会等于较大的浮点数! 所以1e38f + 1 - 1e38f = 1e38f - 1e38f = 0

4. 代码

#include <stdio.h>

// simple ieee 754 single precision float number

// addition arithmetic.

// format:

// S  E   F

// 1  8   23

float test1(float a, float b)

{

    float c = ;

    unsigned int p1 = *((unsigned int *)&a);

    unsigned int p2 = *((unsigned int *)&b);

    unsigned int    t;

    // compute exponent difference

    // essentially, we must let two number's exponent be same

    int e1 = (p1 << ) >> ;

    int e2 = (p2 << ) >> ;

    int diff = e1 - e2;

    if (diff < ) {

        diff =  - diff;

        t = p1;

        p1 = p2;

        p2 = t;

        e1 = e2;

    }

    //convert mantissa to signed integer

    // there is a hidden bit

    //:) i do not want to handle minus number here

    //

    int p3 = p1 | 0x00800000;

    p3 = p3 & 0x00ffffff;

    int p4 = p2 | 0x00800000;

    p4 = p4 & 0x00ffffff;

    //mantissa should be shift right according to difference of

    //exponent.

    unsigned int result = p3 + (p4 >> diff);

    if (result >= 0x01000000) {

        result = result >> ;

        e1 = e1 + ;

    }

    // combination

    result = result&(~0xFF800000) | (e1 << );

    c = *((float *)&result);

    return c;

}

int _tmain(int argc, _TCHAR* argv[])

{

    float c = test1(4.1f, 1.0f);

    return ;

}

5. 流程图

6. 参考文献

https://en.wikipedia.org/wiki/Single-precision_floating-point_format

http://www.cnblogs.com/cornsea/archive/2010/09/18/1830366.html

【原创】为什么浮点数1e38f + 1 - 1e38f等于0的更多相关文章

  1. 【js奇妙说】如何跟非计算机从业者解释,为什么浮点数计算0.1+0.2不等于0.3?

    壹 ❀ 引 0.1+0.2不等于0.3,即便你不知道原理,但也应该听闻过这个问题,包括博主本人也曾在面试中被问到过此问题.很遗憾,当时只知道一句精度丢失,但是什么原因造成的精度丢失却不太清楚.而我在查 ...

  2. 深入理解JavaScript系列:为什么03-0.2不等于0.1

    五一宅家看书,所以接着更新一篇文章. 今天讲一下为什么03-0.2不等于0.1这个问题. 有点标题党的味道,在JavaScript中,当你试着对小数进行加减运算时,有时候会发现某个结果并非我们所想的那 ...

  3. 如何解决JavaScript中0.1+0.2不等于0.3

    console.log(0.1+0.2===0.3)// true or false?? 在正常的数学逻辑思维中,0.1+0.2=0.3这个逻辑是正确的,但是在JavaScript中0.1+0.2!= ...

  4. Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题

    版权声明:本文为博主原创文章,未经博主允许不得转载. 正常情况下调用系统相机拍照: 如果拍照后点击的是“确定”图标,返回的resultCode = -1(Activity.RESULT_OK): 如果 ...

  5. 为什么js中0.1+0.2不等于0.3,怎样处理使之相等?(转载)

    为什么js中0.1+0.2不等于0.3,怎样处理使之相等? console.log(0.1+0.2===0.3)// true or false?? 在正常的数学逻辑思维中,0.1+0.2=0.3这个 ...

  6. 为什么在JavaScript中0.1+0.2不等于0.3?

    0.1+0.2不等于0.3?是不是有点颠覆你的认知,但是,在js中,是真实存在的! console.log(0.1+0.2); // 0.30000000000000004 其实这都是因为浮点数运算的 ...

  7. mytatis将Integer等于0识别成空字符串

    在进行myBatis条件查询的时候,会有如下操作: <if test="delFlag !=null and delFlag != ''"> and t.del_fla ...

  8. false等于0???

    看到一个函数strpos($string,$str),用于在字符串$string中查找$str,如果在$string中查找到$str,则返回第一次出现的位置,起始位置为0:如果$string中不包含$ ...

  9. 【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取”产品付费数量等于0的问题”】

    转的别人的 看到很多童鞋问到,为什么每次都返回数量等于0?? 其实有童鞋已经找到原因了,原因是你在 ItunesConnect 里的 “Contracts, Tax, and Banking”没有完成 ...

随机推荐

  1. window下github的学习心得

    准备工作: 安装git: 1.下载地址:http://msysgit.github.io/ 2.安装:本人是一路next的,现在没发现有什么问题.详细的安装过程参考:https://jingyan.b ...

  2. appium:运行脚本时,报404的解决办法

    对于报404的错,不要怀疑,在环境正常的情况下,一定是你的端口被占用了. 就用:查看端口:netstat -aon|findstr 5037 查看进程:tasklist /fi "PID e ...

  3. [swarthmore cs75] Compiler 2 – Boa

    课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第4次大作业. A-Normal Form 在80年代,函数式语言编译器主要使用Continua ...

  4. 从Typescript看原型链

    话不多说先来段代码 class Parent { private name:string; constructor(name) { this.name = name; } public getName ...

  5. 谈谈npm依赖管理

    引言 现在的前端开发几乎都离不开nodejs的包管理器npm,比如前端在搭建本地开发服务以及打包编译前端代码等都会用到.在前端开发过程中,经常用到npm install来安装所需的依赖,至于其中的技术 ...

  6. Java开发环境配置(Jdk、Tomcat、eclipse)

    Java项目通常会在像eclipse这样的集成开发工具上进行高效的开发,开发之前需要进行一系列的安装及配置,会经过以下几个步骤: 1.官网上下载jdk.tomcat.eclipse 2.安装上面下载的 ...

  7. 第71节:Java中HTTP和Servlet

    第71节:Java中HTTP和Servlet 前言 哭着也要看完!!!字数: 学习xml和TomCat 会写xml,看懂xml 解析对象 SAXReader reader = new SAXReade ...

  8. LabVIEW(四):数据存储和文件IO

    1.使用NI数据采集板卡来进行数据保存和文件I/O操作.2.在一个典型的测试测量系统当中,包括:信号调理.信号采集.信号分析.信号显示.数据存储.数据存储:将采集到的数据储存到磁盘上,以备日后离线分析 ...

  9. SpringBoot+Mybatis集成搭建

    本博客介绍一下SpringBoot集成Mybatis,数据库连接池使用alibaba的druid,使用SpringBoot微框架虽然集成Mybatis之后可以不使用xml的方式来写sql,但是用惯了x ...

  10. 向github提交代码不用输入帐号密码

    解决方案:方案一: 在你的用户目录下新建一个文本文件.git-credentials Windows:C:/Users/username Mac OS X: /Users/username Linux ...