【原创】为什么浮点数1e38f + 1 - 1e38f等于0

By | 07月27日
Advertisement

1. 问题

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

2. 分析

    int ii = 2; //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 + 1; //3f 80 00 00  (0011 1111 1000 0000 0000 0000 0000 0000)
    float l = i + 1 + 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. 代码

【原创】为什么浮点数1e38f + 1 - 1e38f等于0
【原创】为什么浮点数1e38f + 1 - 1e38f等于0

#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 = 0;

    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 << 1) >> 24;

    int e2 = (p2 << 1) >> 24;

    int diff = e1 - e2;

    if (diff < 0) {

        diff = 0 - 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 >> 1;

        e1 = e1 + 1;

    }

    // combination

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

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

    return c;

}

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

{

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

    return 0;

}

View Code

5. 流程图

【原创】为什么浮点数1e38f + 1 - 1e38f等于0

6. 参考文献

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

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

Similar Posts:

  • 我的疑问:计算机怎么感知-128等于-0的?

    我的疑问:计算机硬件怎么感知-128等于-0? 以下面的程序入手分析: int main() { char a[1000]; int i; for(i=0; i<1000; i++) { a[i] = -1-i; } printf("%d",strlen(a)); return 0; } 分析上面的程序:a[i]=-1,-2,-3,-,-254,-255-,但是,这些数在计算机内部是怎么存的? 大前提是(char的默认状况是存的有符号数,并且数据在计算机内部是以补码的形式存的)

  • 我的疑问:计算机硬件怎么感知-128等于-0?

    我的疑问:计算机硬件怎么感知-128等于-0? 以下面的程序入手分析: int main() { char a[1000]; int i; for(i=0; i<1000; i++) { a[i] = -1-i; } printf("%d",strlen(a)); return 0; } 分析上面的程序:a[i]=-1,-2,-3,-,-254,-255-,但是,这些数在计算机内部是怎么存的? 大前提是(char的默认状况是存的有符号数,并且数据在计算机内部是以补码的形式存的)

  • 100-1为什么要等于0“心情”

     生活就是一团乱麻,油盐酱醋混在一起都分不出任何味道.为什么日子过得么这累,为什么没有一个人能理解我,为什么没有人能够在背后助我一臂之力. 创业艰苦都是必然的,为什么不能分享创业的快乐呢?而中中享受这个过程呢?我是普普通通的人而不是神,全天下所有人创业并不都是一帆风顺的.男人在这个过程中,往往需要得到的是什么呢?并不是你对我的工作上的帮助,生活上的帮助.其实这些你都做得不够,但我不怪你.在生活上我也没有很好的关心过你,但是必须要明白最终我是为了什么? 时不时在朋友或亲人面前夸夸我怎么怎么好,

  • 我说在某些主板上int 13;AH = 02H,返回值AL等于0你信吗?

    DISK - READ SECTOR(S) INTO MEMORY AH = 02h AL = number of sectors to read (must be nonzero) CH = low eight bits of cylinder number CL = sector number 1-63 (bits 0-5) high two bits of cylinder (bits 6-7, hard disk only) DH = head number DL = drive num

  • 【原创】寻找方程等于0的数值算法总结

    机器学习中,很多问题都可以归结为寻找 f(x)=0 的点(例如,凸优化问题,寻找导数为0的点).很多时候f(x)=0的解析解很难计算,下面,我们就总结一下该问题的数值计算方法. 1. Newton's Method(牛顿法) 牛顿法是利用函数在当前点的切线作为函数的近似,寻找当前点切线=0的点,作为下一个搜寻点.牛顿法的迭代公式如下: [{x_{n + 1}} = {x_n} - frac{{f({x_n})}}{{f'({x_n})}}{mkern 1mu} ] 下面是牛顿法法收敛的动态图示:

  • [置顶] 求方程 的根,用三个函数分别求当b^2-4ac大于0、等于0、和小于0时的根,并输出结果。从主函数输入a、b、c的值。

    #include <iostream> #include <cmath> #include <iomanip> using namespace std; float x1,x2,disc,p,q; int main() { void greater_than_zero(float,float); void equal_than_zero(float,float); void smaller_than_zero(float,float); float a,b,c; cin

  • 原创作品:手机泡泡堂 1.0 下载

    手机泡泡堂 1.0 版本 作者:S.F. QQ:410000 EMail:mailluck at gmail dot com 运行环境要求:支持J2me MIDP 2.0 的彩屏手机 也可以用手机模拟器模拟运行,参考下载:J2ME Wireless Toolkit 2.2.exe 手机访问地址:http://farouter.oicp.net/SJ_POPTang/poptang.asp 游戏下载地址: http://farouter.oicp.net/SJ_POPTang/jbombman.j

  • php的一个判断值是否等于0的陷阱

    原文地址:http://blog.fj18.com/post/199.html 先给一段代码: $a = ' Zero ' ; $b = 0 ; if ( $a == $b ) { echo ' True ' ; } else { echo ' False ' ; } 我们预期的结果是False吧,但很遗憾,输出结果是True. 为什么会这样呢?原来是PHP在做字符串和数字进行比较时,会把字符串转为数字,如果字符串首字母不是数字或-时,会被转成0,然后杯具就发生了. 解决办法有2种: 1.如果确

  • 解决 veiw 之间 因为父view alpha 等于0 导致全部透明的问题

    首先 先看一段代码,矛盾的起因, 因为父view 的alpha= 0 ,而又想让子view 能够显示出来,不受父view的alpha=0 的影响. UIView *view = [[UIView alloc] init]; view.backgroundColor = [UIColor redColor]; //因为下面的label 没有显示 是因为父view的alpha = 0 view.alpha = 0; view.frame = CGRectMake(30, 100, 200, 200)

  • C语言浮点数除法,除数为0不报错。

    http://bbs.mydigit.cn/read.php?tid=487097 最近学习AVR 脉宽测量时怎么此语句出来结果为0 int a,b; uchar pwm; pwm=(float)(a/b)*100; // 乘 100 改为乘 100.0 即可 pwm=((float)a/(float)b)*100; http://feijiafan.blog.163.com/blog/static/7732612620140249304526/

Tags: