• C++ 求幂函数pow()的输出问题


    C++ 求幂函数pow()的输出问题

    前言

    最近在打一些算法题目的时候,遇到了不少cpp的一些bug,在其中有不少让我困惑了很久!

    今天的主角就是如此,本文的pow函数,在不同编程环境下,出现了不同的输出情况。

    问题现状

    先上代码

    #include
    #include
    #include
    
    typedef long long ll;
    #define endl '\n'
    typedef std::string string;
    
    int main()
    {
    	int num;
    	scanf("%d", &num);
    	string snum = std::to_string(num);
    	int len = snum.length();
    	int k = std::pow(10, len);
    	printf("%d\n", k);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这个代码的逻辑是,输入一个字符串,根据输入字符串的长度len,然后输出10^len(10的len次幂)。

    然后我选取 devc++visual studio 2022 两个IDE来测试这个代码。

    devcpp

    在这里插入图片描述

    visual studio

    在这里插入图片描述

    可以看到在不同的 IDE 下的运行结果是截然不同的。且可以看出来,devcpp的结果是我们在编写程序时不希望或者不在我们预料范围内,而visual 的结果则是符合预期的。

    那么,为什么会出现这样的问题呢,为了能让问题更加清楚,我将代码修改了一下。

    #include
    #include
    #include
    
    typedef long long ll;
    #define endl '\n'
    typedef std::string string;
    
    int main()
    {
    	int num;
    	int i = 0;
    	while(~scanf("%d", &num))
    	{
    		num = std::pow(10, i++);
    		printf("%d\n", num);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    改动后,每次循环输入一个数字,当然这个数字是个没用的 临时变量,我们会0开始,用pow函数得到10的幂次。

    运行结果如下

    在这里插入图片描述

    可以看到,在 int 变量范围内时,原本应该输出100,10000,100000000,1000000000 四个数字,pow输出了该值 - 1的结果。

    问题原因

    在逛了很多blog,和像百度回答,stackoverflow等网站后,对这个问题有了比较合理的解释。

    感兴趣的可以看这个关于C ++:幂函数输出错误-C | 码农家园 (codenong.com)

    这是我找到的对这个问题比较好的讨论。

    我们先看下百度对pow的解释

    在这里插入图片描述

    在这里插入图片描述

    我们发现,pow有多个重载,且我们在使用的时候编译器应该会有警告,但是这和我们遇到的问题是没有特别大的关系。

    在这里插入图片描述

    我们再看这个解释,这里结合百度百科关于pow函数的重载,我的解释是:

    在使用变量的时候,函数会将变量转化,而求值(返回值)的结果会最终转化为double,在double转int的过程中,会出现精度丢失的问题,这里其实是pow函数的问题,运算的结果会出现一个小于100,但极度接近100的数,比如99.99996之类的,然后由于cpp 的 doubleint 发生的 精度丢失 的问题,从而使结果变为99。

    那,为什么,不同的ide的输出结果会不同?

    我想这应该是两个ide对pow的解释不同,或者说优化处理不同。

    visual 的环境是window cpp开发, 而devcpp则是基于MinGW,不同的环境确实会在这些库函数的细节之处有所不同。

    解决方法

    如何避免这个问题,或者怎么解决呢?我们可以这样子。

    在函数的输出后加一个很小的浮点数,或者可以直接加0.5,确保实现四舍五入。

    代码如下

    Code(cpp)

    #include
    #include
    #include
    
    typedef long long ll;
    #define endl '\n'
    typedef std::string string;
    
    int main()
    {
    	int num;
    	int i = 0;
    	while(~scanf("%d", &num))
    	{
    		num = std::pow(10, i++) + 0.5;
    		printf("%d\n", num);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果

    在这里插入图片描述

    这样就可以避免出现因为pow函数精度丢失引起的数值错误问题了!

    后话

    好久没更新了,之前一直在高强度上课+集训,以及一些其他的事情影响,后续加油吧!

  • 相关阅读:
    【Mysql】复合查询详解+实战操作(多表查询、自链接、子查询等)
    Web jQuery—属性、元素、尺寸和位置
    Yolov8有效涨点:YOLOv8-AM,添加多种注意力模块提高检测精度,含代码,超详细
    将虚拟机VMware从C盘移动到E盘
    从零开始的深度学习之旅(2)
    基于强化学习的节能路由(Matlab代码实现)
    【光学】基于Matlab模拟干涉条纹图
    Hadoop 王者 Cloudera 新转型,定位为混合数据公司
    ORB-SLAM2 ---- Tracking::TrackWithMotionModel函数
    【JAVA-Day38】深入了解Java常用类 String:字符串操作的技巧和方法
  • 原文地址:https://blog.csdn.net/weixin_54891898/article/details/126456059