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

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

前言

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

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

问题现状

先上代码

#include<cstdio>
#include<string>
#include<cmath>

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;
}

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

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

devcpp

在这里插入图片描述

visual studio

在这里插入图片描述

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

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

#include<cstdio>
#include<string>
#include<cmath>

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;
}

改动后,每次循环输入一个数字,当然这个数字是个没用的 临时变量,我们会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<cstdio>
#include<string>
#include<cmath>

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;
}

运行结果

在这里插入图片描述

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

后话

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

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值