C/C++浮点数使用的两个注意事项详解

 更新时间:2023年02月06日 09:31:02   作者:摆烂小青菜  
浮点数都是有符号的,没有 unsigned 浮点数,下面这篇文章主要给大家介绍了关于C/C++浮点数使用的两个注意事项,文中通过图文介绍的非常详细,需要的朋友可以参考下

一.回顾浮点数的存储与读取

浮点数的存入与读取流程总览:

二.浮点数使用的第一个注意事项

由于浮点数存入时很可能发生有效数值M二进制序列的截断以及被截去的序列的最高位的四舍五入而造成精度损失,所以两个浮点数直接用操作符进行比较很可能会得到不符合预期的结果。

举个例子:

int main()
{
    float a = 3.12f;
    a += 0.02f;
   
    float b = 3.14f;
 
    std::cout << (a == b) << std::endl;
    std::cout << (a > b) << std::endl;
    std::cout << (a < b) << std::endl;
 
    return 0;
}

简单调试一下代码:

上述代码中,a最终的值和b的值在数学上应该是相同的,但是由于精度丢失而导致了最后a<b,如果这时a和b直接用运算符进行比较则无法得到预期的结果。

两个浮点数的比较应该使用如下方式:

对于浮点数而言比较合适的精度为:0.000001

对于双进度浮点数而言比较合适的精度为:0.0000000000000001

因此可以定义两个宏:

#define epf 1e-6
#define epd 1e-16

f,f1,f2代表单精度浮点数,d,d1,d2代表双精度浮点数。

判断浮点数是否等于0:

要判断一个单精度浮点数是否等于0:if(fabs(f) <= eps );
要判断一个双精度浮点数是否等于0:if(fabs(d) <= epd);
判断两个浮点数是否相等:

要判断两个单精度浮点数是否相等:if(fabs(f1 - f2) <= eps);
要判断两个双精度浮点数是否相等:if(fabs(d1 - d2) <= epd);

注:fabs是求浮点数绝对值的函数。声明在<iostream>头文件中。

#define eps 1e-6
int main()
{
    float a = 3.12f;
    a +=0.02f;
    float b = 3.14f;
    if (fabs(a - b) <= eps)
    {
        std::cout << "a==b" << std::endl;
    }
    else
    {
        std::cout << "a!=b" << std::endl;
    }
    return 0;
}

三.浮点数使用的第二个注意事项 

由于浮点数存入时可能发生数据截断,因此两个绝对值相差巨大的浮点数进行加减运算很多时候是没有意义的。

以十进制数为例来说明这个问题:

代码验证:

int main()
{
    float a = 1e38;
    std::cout << a << std::endl;
    
    float b = 1000;
    a = a + b;
    std::cout << a << std::endl;
 
    a = a - b;
    std::cout << a << std::endl;
    return 0;
}

附: 观察内存中的FLT_MAX和FLT_MIN

C/C++中的FLT_MAX都被宏定义为浮点数绝对值最大的值

将FLT_MAX存入内存中:

将a的二进制序列分割为SEM的形式 :

其指数位不是全1

C/C++中的FLT_MIN被宏定义为绝对值最接近于0的浮点数 

将FLT_MIN存入内存中:

其指数位不是全0 

补充:C 语言两个浮点数比较大小的办法

浮点数并非真正意义上的实数,只是其在某个范围内的近似。

因此两个浮点数比较大小时,不能简单地使用大于小于号进行比较,应该判断连个浮点数差值的绝对值是否近似为0。

#include <stdio.h>
#include <math.h>
 
// 这里的 EPS 是自己定义的精度
#define EPS 1e-7     // 判断浮点数是否位于0的一个很小的邻域内[-EPS,EPS]内

int main(void)
{
    /* 判断一个浮点数是否等于 0*/
    float a;
    scanf("%f", &a);
    if(fabs(a) <= EPS)  // a=0
        ...
    else if(a > EPS)    // a>0
        ...
    else                // a<0
        ...
 
    /* 比较两个浮点数大小 */
    float a,b;
    scanf("%f%f",&a, &b);
    if(fabs(a-b) <= EPS)  // a=b
        ...
    else if( (a-b) > EPS)  // a>b
        ...
    else                   // a<b
        ...
}

总结

到此这篇关于C/C++浮点数使用的两个注意事项的文章就介绍到这了,更多相关C/C++浮点数注意事项内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言中栈的结构和函数接口的使用示例

    C语言中栈的结构和函数接口的使用示例

    这篇文章主要介绍了C语言中栈的结构和函数接口的使用,类似很多软件都有撤销的操作,这其实就是用栈这种方法来实现的,当然不同的软件具体实现代码会有差异,不过原理大多都是一样的
    2023-02-02
  • C++开发之PugiXML库基础用法示例详解

    C++开发之PugiXML库基础用法示例详解

    PugiXML库是一个功能强大、简单易用的C++ XML解析库,它提供了一组方便的函数来解析、创建和修改XML文档,本文介绍了如何使用PugiXML库来解析、创建和修改XML文档,以及如何处理错误和异常,感兴趣的朋友跟随小编一起看看吧
    2024-03-03
  • C++深入探究哈希表如何封装出unordered_set和unordered_map

    C++深入探究哈希表如何封装出unordered_set和unordered_map

    哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方,说起来可能感觉有点复杂,我想我举个例子你就会明白了,最典型的的例子就是字典
    2022-06-06
  • C++中的聚合类定义与用法分析

    C++中的聚合类定义与用法分析

    这篇文章主要介绍了C++中的聚合类定义与用法,结合实例形式分析了C++中聚合类的简单定义、使用方法与相关注意事项,需要的朋友可以参考下
    2017-08-08
  • C++实现班级成绩管理系统

    C++实现班级成绩管理系统

    这篇文章主要为大家详细介绍了C++实现班级成绩管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • CStdioFile的用法详细解析

    CStdioFile的用法详细解析

    CStdioFile 不支持Duplicate,LockRange,和UnlockRange 这几个CFile 函数。如果在CStdioFile 中调用了这几个函数,将会出现CNoSupported 异常
    2013-09-09
  • 浅谈C++ 类的实例中 内存分配详解

    浅谈C++ 类的实例中 内存分配详解

    下面小编就为大家带来一篇浅谈C++ 类的实例中 内存分配详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • CMake 生成静态库与动态库的方法步骤

    CMake 生成静态库与动态库的方法步骤

    本文主要介绍了CMake 生成静态库与动态库的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • C++开发之CRC校验实例详解

    C++开发之CRC校验实例详解

    这篇文章主要介绍了C++开发之CRC校验实例详解的相关资料,需要的朋友可以参考下
    2017-07-07
  • 采用C++实现区间图着色问题(贪心算法)实例详解

    采用C++实现区间图着色问题(贪心算法)实例详解

    这篇文章主要介绍了采用C++实现区间图着色问题(贪心算法),很经典的算法问题,需要的朋友可以参考下
    2014-07-07

最新评论