OI中C++的常数优化详解

Part0

ppt版本
常数优化有效性测试
参考文献:论程序底层优化的一些方法和技巧
注:此文件已经被我下载并上传,如果想要pdf文件但是下载不了道客巴巴文档可以私信找我要下载链接和密码。

Part1 常数优化前置概念

如何测量函数的耗时

根据前文,我们有必要评估函数的耗时,从而进行有效的优化。
使用头文件 c t i m e ctime ctime t i m e . h time.h time.h中的clock()函数,此函数返回当前的总运行时间。
样例代码:

#include<ctime>
int tmp=clock();
function();
int _time=clock()-tmp;

这段代码运行后,_time变量就表示函数function()的运行时间。
其单位为:ms(毫秒)
为了保证测量精确度,因为对于耗时较小的函数_time可能会为0,所以我们应该多次运行该函数取它们的总时间并求平均值。
这种方法与测量纸的厚度的方法是一样的。用for循环实现。

一些基本的语句的耗时

  • 整数加减:1(个时钟周期,下同)
  • 整数位运算:1
  • 整数乘法:2
  • 整数除法:21
  • 浮点加减:3
  • 浮点除法:35
  • 浮点开根:60
  • 指针加法:1

各类型比较:

int运算是最快的。unsigned无符号数做除法比有符号数快。
float比任何整数运算更慢,double比float慢,long double最慢。
注意:实测int比char和short具有更快的速度。

Part2 常数优化方法

运算优化

正如Part01所说,不同的数据类型以及它们的各运算速度是不一样的。

3.1.1 一般情况的运算优化

1.优化除法/取模运算。例:将a/b==c/d化为a\*d==c\*b,事实上,这对于整数来说也能够保持精度。另外,unsigned无符号数比有符号数能够更快地完成除法运算。而对于取模,可以将其优化为:
inline int MOD(int x){return x<Mod?x:x%Mod;}
而对于某些题目,仅需要对答案取模。这类题目要边运算边取模的目的一般是防止溢出。
故我们甚至可以写成这样:
inline int MOD(int x){return x<=0x3f3f3f3f?x:x%Mod;}
如果是乘法,我们相应地可以写成:
inline int MOD(int x){return x<=45000?x:x%Mod;}
总之,这个范围要保证结果在计算时不会有溢出的风险。但采用了这种方式后,最后输出时一定要取模。
对于负数取模的优化:
inline int MODF(int x){x=MOD(x);return x<0?x+MOD:x;}

2.减少浮点除法

由于浮点运算满足运算定律,优化的余地很大。除了整数的那些方法外,还有很多技巧。
举两个骆爷pdf里的例子:

a/b+c/d化为(a*d+b*c)/(b*d)
int x=a/b,y=c/d,z=e/f;化为:
int t=b*d*f;
int x=a*d*f/t,y=c*b*f/t,z=e*b*d/t;

诸如此类。

·3.优化浮点运算

例如,要求保留2位小数,可以扩大10000倍然后用int/long long代替。或者左移14位(214=16384),然后输出的时候乘以2(-14)≈0.00006103515625再保留两位小数即可。

3.1.2 特殊情况下的运算优化

注:位运算的优先级低于±*/

1.乘除2的整数幂
x*(2^k)=x<<k   x/(2^k)=x>>k
2.乘除常数的优化
x*10=(x<<1)+(x<<3)注:实测x+(
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值