软件安全-2.算法优化

2.1 优化基本运算

很多细微的代码都可以进行优化,其中最常见的是乘法和除法的优化.

比如以下代码:

for(i=0;i<1000;i++){
    sum+=i*4;
}

如果使用移位来代替乘法运算,可以使性能提高.重写后的代码如下:

for(i=0;i<1000;i++){
    sum+=(i<<2);
}

同样,向右移位相当于除于2,比如将两个数字相加之后取平均值,传统代码如下:

int mid = (hi+lo)/2

实际上,该代码可以进行优化,将两个数字的和右移,此时CPU不需要做一个除法指令,节省资源,代码如下:

int mid = (hi+lo)>>1;

求余运算也可以进行优化,比如:

a=a%8;

可以改为:

a=a&7;

该代码有助于提高性能,但如前所述,可读性变差了

此外,整数除法是整个运算中最慢的,所以应该尽可能避免.

对于连除,有时可以用乘法代替

以下是不好的代码:

int i,j,k,m;
m=i/j/k;

推荐代码:

int i,j,k,m;
m=i/(j*k);

以上操作的副作用是:有可能在乘积运算时,整数会溢出,所以只能在一定范围的除法中使用

2.2 优化流程

流程主要包括以下两类:选择和循环

1.选择结构的优化

在选择语句中,可以利用一些手段提高运行性能,如:

  • 充分将可能性大的分支写在前面;
  • 充分利用短路判断运算符

如下代码为根据学生的分数判断及其等级:

public String getGrade(int score) throws Exception{
    String msg = null;
    if(score>=60&&score<=100){
        msg ="通过";
    }elseif(score>=0&&score<60){
        msg="未通过"
    }else{
        throw new Exception();
    }
    return msg;
}

该程序中,根据学校以往的统计经验,如果学生不能通过的概率较大,那么第二个if分支就应该调到前面去

另外,短路运算符有时也可以提高性能

​ 如下代码:

if(条件1&&条件2)

可以将不成立概率较大的条件放在前面.

​ 又比如:

if(条件1||条件2)

可以将成立概率较大的条件放在前面.

另外,在使用if-if结构和if-else if结构效果相同的情况下,用if-else if可以使程序减少不必要的判断

在用if判断某些值是否相等时,尽量将变量作为比较对象,如下代码:

if(a==3)

改成:

if(3==a)

这是为了消除万一程序员将==写成=造成的隐患

在选择流程的嵌套上,代码会按照顺序进行比较,匹配时就跳转到满足条件的语句执行。所以可以对嵌套可能的值依照发生的可能性进行排序,把最有可能的放在第一位,这样可以提高性能。

比如,以下代码得到一个年份的某个月份的天数:

public String getDayNumber(int year,int month{
	if(year是闰年){
        //得到各个月份的天数
    }else{
        //得到各个月份的天数
    }
	
 }

如果每个月份被输入的概率相同,那么就没有必要首先判断年份是否是闰年。因此,代码可以改为:

public String getDay/Number(int year,int month){
	if(月份为2){
    	//判断年份是否是闰年}
   		//得到天数
    }
	else{
    //得到其他各个月份的天数
	}
}

综上所述,当if-else if-else语句中的分支很多时,为了减少比较的次数,明智的做法是把多分支if-else if-else语句转为嵌套if-else if-else语句。把发生频率高的情况放在一个if语句中,并且是嵌套if-else if-else语句的最外层,发生频率相对低的情况放在另一个if语句中。

2 循环的优化

循环的特点是可能会反复执行一些代码,因此,在循环中,有很多可以优化的场合,优化得好,可以大大提高系统性能。

如下代码:

Vector v;
for(int i=0;i<v.size();i++){
    //一些操作
}

该代码中,循环内i<v.size();会反复执行,系统会重复计算v的大小。因此,这段代码是可以优化的

优化方法是:可以让系统只调用v.size()一次,代码如下:

Vector v;
int n = v.size();
for(int i=0;i<n;i++){
    //一些操作
}

不过,如果是对集合v进行反向遍历,就没有必要进行优化了,因为此时v.size()只会调用一次。如下代码:

Vector v;
for(int i=v.size()-1;i>=0;i--){
    //一些操作
}

posted @ 2021-08-01 18:41  1ink  阅读(45)  评论(0编辑  收藏  举报