float类型加法精度损失问题(C++)

问题

unsigned int a = 406682816;
a = a+1.0f;

奇怪的就是:a依然是406682816,并没有加一。网上查了一些资料,这里分享一下原因。

分析与验证

测试代码

    int a=406682816;
    int c=a+1.0f;

    int mask = 1;
    // 浮点类型的a
    float fa = a; 
    // 浮点类型的a+1.0f
    float fc = a+1.0f;

    cout << a << endl;
    cout << c << endl;

    cout << endl << "a bits" << endl;
    for ( int i=31;i>=0;i-- )
    {
        cout << ((*((int*)&a))>>i & mask );
    }

    cout << endl << "fa bits" << endl;
    for ( int i=31;i>=0;i-- )
    {
        cout << ((*((int*)&fa))>>i & mask );
    }

    cout << endl << "fc bits" << endl;
    for ( int i=31;i>=0;i-- )
    {
        cout << ((*((int*)&fc))>>i & mask );
    }
    cout << endl;

输出

406682816
406682816

a bits
00011000001111010111110011000000
fa bits
01001101110000011110101111100110
fc bits
01001101110000011110101111100110
// fa和fc的内存值完全一致

原因结论

float类型的内存分布在IEEE 754标准里有规定:对于大小为32-bit的浮点数(32-bit为单精度,64-bit浮点数为双精度,80-bit为扩展精度浮点数)

  1. 其第31 bit为符号位,为0则表示正数,反之为复数,其读数值用s表示;
  2. 第30~23 bit为幂数,其读数值用e表示;
  3. 第22~0 bit共23 bit作为系数,视为二进制纯小数,假定该小数的十进制值为x;

float类型的数值得出的公式计算示例如下(截自网络):

20170215225457756.png

也即,float类型可以用于数值计算的位数少于int(只有23位),通过符号位,幂数以及系数位来做计算,示例中做了1.0f的加法后,并没有改变内存的布局,所以值并未变化。

这里也从侧面提醒我们,在做要求精度的计算时,避免使用float类型是上佳之策,否则,即是我们明白float类型的计算原理依然会踩坑..

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小L的魔法馆

新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)--B-杨老师的游戏

43790
来自专栏小樱的经验随笔

numpy用法小结

前言   个人感觉网上对numpy的总结感觉不够详尽细致,在这里我对numpy做个相对细致的小结吧,在数据分析与人工智能方面会有所涉及到的东西在这里都说说吧,也...

45340
来自专栏Petrichor的专栏

python: random模块

  在numpy 和 tensorflow 中有 相同功能 的实现, 见 《tensorflow: Constants, Sequences, and Ra...

22010
来自专栏社区的朋友们

sizeof 知多少? (上)

稍熟悉 C/C++ 的朋友,对于 sizeof 肯定不陌生,通过它我们可以知晓某个类型或者实例的内存大小( 以字节计 ),网上关于这个话题的信息其实挺多的,但是...

19100
来自专栏数据结构与算法

P3382 【模板】三分法

题目描述 如题,给出一个N次函数,保证在范围[l,r]内存在一点x,使得[l,x]上单调增,[x,r]上单调减。试求出x的值。 输入输出格式 输入格式: 第一行...

36490
来自专栏技术总结

算法(2)

25490
来自专栏落影的专栏

iOS开发-OpenGL ES入门教程2

教程 OpenGLES入门教程1-Tutorial01-GLKit 这次的是shader编译链接、glsl入门和简单图形变换。 OpenGL ES系列教程在这...

33480
来自专栏不止思考

算法的时间与空间复杂度(一看就懂)

算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有...

12720
来自专栏前端黑板报

一个数字截取引发的精度问题(四)

这篇是精度问题的最后一篇,要是想看前面的,请看微信历史记录。 做前端的都感觉JS这语言巨坑无比,兼容性让你摸不到头脑,甚至还会让你脱发。一些初学者遇到: 0.1...

277100
来自专栏CVer

刷题笔记 | 剑指Offer 03 二维数组中的查找

本文主要讲解《剑指Offer》中第03题"二维数组中的查找",介绍题目、解决思路、解题步骤,并分别以C++和Python编程语言解答此题。

20630

扫码关注云+社区

领取腾讯云代金券