【原创】各类输出与输出优化的比较

一、背景

做题的时候,经常写读入优化,而读入优化的核心是“getchar”,它比scanf快多了。

我不禁想,有没有“putchar”呢?有。那么有没有输出优化呢?它和printf和cout谁更快呢?

于是就写下了这个验证程序。


二、验证


在网上搜了一下,主要有两种输出优化。

第一种是比较常见的:

inline void Putint_usual(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) Putint_usual(x/10);
    putchar(x%10+'0');
}

第二种是使用数组的的:

inline void Putint_array(int x)
{
	int buf[30]={0};
	if (x<0) putchar('-'),x=-x;
	buf[0]=0;
	while (x) buf[++buf[0]]=x%10,x/=10;
	if (!buf[0]) buf[0]=1,buf[1]=0;
	while (buf[0]) putchar('0'+buf[buf[0]--]);
}

以上两种的基本思路就是把这个数的每一位都求出来,然后依次用putchar输出。


除此之外,c语言还自带有printf,c++还有cout。


于是我写了一个程序。


#include<cstdio>
#include<ctime>
#include<algorithm>
#include<windows.h>
#include<iostream>
using namespace std;
inline void pri(int p)
{
	printf("%d",p);
}
inline void Putint_usual(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) Putint_usual(x/10);
    putchar(x%10+'0');
}
inline void Putint_array(int x)
{
	int buf[30]={0};
	if (x<0) putchar('-'),x=-x;
	buf[0]=0;
	while (x) buf[++buf[0]]=x%10,x/=10;
	if (!buf[0]) buf[0]=1,buf[1]=0;
	while (buf[0]) putchar('0'+buf[buf[0]--]);
}
inline void c(int p)
{
	cout<<p;
}
double t1,t2,ans1,ans2,ans3,ans4;
int main()
{
	const int T=300000;//测试多少个数

	freopen("asdfghjkl.txt","w",stdout);
	
	t1=clock();
	for(int i=1;i<=T;i++) Putint_array(i);
	t2=clock();
	ans1+=(t2-t1)/1000;
	system("cls");

	t1=clock();
	for(int i=1;i<=T;i++) Putint_usual(i);
	t2=clock();
	ans2+=(t2-t1)/1000;
	system("cls");

	t1=clock();
	for(int i=1;i<=T;i++) pri(i);
	t2=clock();
	ans3+=(t2-t1)/1000;
	system("cls");

	t1=clock();
	for(int i=1;i<=T;i++) c(i);
	t2=clock();
	ans4+=(t2-t1)/1000;
	system("cls");

	fclose(stdout);
	freopen("out.txt","w",stdout);
	
	printf("When T=%d: \n",T);
	printf("Putint_array took %.2lf second\n",ans1);
	printf("Putint_usual took %.2lf second\n",ans2);
	printf("printf took %.2lf second\n",ans3);
	printf("cout took %.2lf second\n",ans4);
}



代码解释:

clock();//取得当前的时间,单位是ms。要算一段时间,只需要用 [(结束的时间)-(开始的时间)],即可,因为单位是ms,所以除以1000,让单位转化成s。需要#include<ctime>或者#include<time.h>

system("cls");//清屏指令,需要#include<windows.h>头文件


补充说明:

1.为了公平起见,四种方式都写在了内链函数里。避免调用函数的时间对程序产生影响。

2.四种方式都非常的不稳定,只运行一次不可信。

3.T是可以更改的

4.因为是比较输出效率,所以说必须输出出来,但是满屏都是数字在飞,特别烦人,所以加了清屏指令。


下面T=30000和T=10000000为例,输出结果为:


When T=300000: 
Putint_array took 0.05 second
Putint_usual took 0.03 second
printf took 0.11 second
cout took 0.08 second


When T=10000000: 
Putint_array took 1.97 second
Putint_usual took 1.51 second
printf took 3.77 second
cout took 2.80 second


所以说,相较起来,常规的输出优化是最快的,而cout擅长输出小数据,比如把输入i换成输出一个很大的数字来看看?


#include<cstdio>
#include<ctime>
#include<algorithm>
#include<windows.h>
#include<iostream>
using namespace std;
inline void pri(int p)
{
	printf("%d",p);
}
inline void Putint_usual(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) Putint_usual(x/10);
    putchar(x%10+'0');
}
inline void Putint_array(int x)
{
	int buf[30]={0};
	if (x<0) putchar('-'),x=-x;
	buf[0]=0;
	while (x) buf[++buf[0]]=x%10,x/=10;
	if (!buf[0]) buf[0]=1,buf[1]=0;
	while (buf[0]) putchar('0'+buf[buf[0]--]);
}
inline void c(int p)
{
	cout<<p;
}
double t1,t2,ans1,ans2,ans3,ans4;
int main()
{
	const int T=5000000;//测试多少个数
	const long INF=(1<<32)-1;

	freopen("asdfghjkl.txt","w",stdout);
	
	t1=clock();
	for(int i=1;i<=T;i++) Putint_array(i);
	t2=clock();
	ans1+=(t2-t1)/1000;
	system("cls");

	t1=clock();
	for(int i=1;i<=T;i++) Putint_usual(INF);
	t2=clock();
	ans2+=(t2-t1)/1000;
	system("cls");

	t1=clock();
	for(int i=1;i<=T;i++) pri(INF);
	t2=clock();
	ans3+=(t2-t1)/1000;
	system("cls");

	t1=clock();
	for(int i=1;i<=T;i++) c(INF);
	t2=clock();
	ans4+=(t2-t1)/1000;
	system("cls");

	fclose(stdout);
	freopen("out.txt","w",stdout);
	
	printf("When T=%d: \n",T);
	printf("Putint_array took %.2lf second\n",ans1);
	printf("Putint_usual took %.2lf second\n",ans2);
	printf("printf took %.2lf second\n",ans3);
	printf("cout took %.2lf second\n",ans4);
}

结果:

When T=5000000: 
Putint_array took 1.11 second
Putint_usual took 0.16 second
printf took 0.88 second
cout took 1.11 second


综上:还是使用输出优化吧!



注意:


以上结果是输出在了Freopen里,但是如果不要Freopen,直接在cmd里输出,会得到完全不一样的结果!(输出在cmd时,printf较快!)


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值