if elseif else条件语句的计算量问题

咱们常常用if elseif else这种条件语句去作分支处理,以前遇到这种语句时就有点困惑,哪一种条件语句放前面,哪一种放后面,不一样顺序是否有计算量和效率上的不一样?在计算量小的时候,其实分别是不大的,可是随着代码量的不断增多,运算量愈来愈大,特别是未来大数据和机器学习等海量数据处理的时候,算法的优点就更加明显.Ps: alphaGo Zero用的处理器只有alphaGo的十分之一,算力不强大,但算法的优点却一举让它成功战胜阿尔法狗,也印证了算法之于算力的关系,可见算法的重要性.此次用一个小例子来讲明代码的计算量优化的问题.php

 

假设咱们有两个箱子,每一个箱子里有从1到10一共10个球,同时从两个箱中分别取一个球,若是两个数都大于8,则中奖.如今要写一个代码,判断是否中奖.算法

 

思路:咱们知道中奖的几率是(2/10)^2=0.04,是一个小几率事件,因此咱们分别从两个方向来统计代码的计算量,一个从大几率开始判断,一个从小几率开始判断.机器学习

 

从大几率开始判断性能

//运算次数初始化
$times = 0;

//先判断大几率事件
for ($i=1;$i<=10;$i++) {
	for ($j=1;$j<=10;$j++) {
		if ($i<=8 && $j<=8) { //若是两个数都小于等于8,则此次判断的运算量为3,运算量+3
			$times += 3;
		} elseif ($i<=8 && $j>8) {/*若是第一个数小于等于8第二个数大于8,则此次判断的计算量为6
			(由于它首先判断了本身不符合上一个条件,此时计算量为3,而后在这里又作了
			一个计算量为3的第二次判断,因此总共的计算量为6)*/
			$times += 6;
		} elseif ($i>8 && $j<=8) {/*到达这里用了7次运算,这里第一个数大于8,因此在到达第一个条件时
			的第一个判断时就为假,而因为php的短路与机制,后面的第二个判断就没有执行,因此第一个条件
			执行了2次运算,同理,第二个条件也执行了2次运算,到达本条件时执行了3次运算,因此一共是7次运算*/
			$times += 7;
		} else {//到这里一共经历了2+2+2=6次判断
			$times += 6;
		}
	}
}

echo $times; //输出运算量,一共424次运算

 

从小几率开始判断学习

$times = 0;
//先判断小几率事件
for ($i=1;$i<=10;$i++) {
	for ($j=1;$j<=10;$j++) {
		if ($i>8 && $j>8) { //若是两个数都大于8,则此次判断的运算量为3,运算量+3
			$times += 3;
		} elseif ($i>8 && $j<=8) { /*若是第一个数大于8第二个数小于等于8,则此次判断的计算量为6
			(由于它首先判断了本身不符合上一个条件,此时计算量为3,而后在这里又作了
			一个计算量为3的第二次判断,因此总共的计算量为6)*/
			$times += 6;
		} elseif ($i<=8 && $j<=8) { /*到达这里用了7次运算,这里第一个数小于等于8,因此在到达第一个条件时
			的第一个判断时就为假,而因为php的短路与机制,后面的第二个判断就没有执行,因此第一个条件
			执行了2次运算,同理,第二个条件也执行了2次运算,到达本条件时执行了3次运算,因此一共是7次运算*/
			$times += 7;
		} else { //到这里一共经历了2+2+2=6次判断
			$times += 6;
		}
	}
}

echo $times; //652次判断

 

能够看出,从几率大的条件开始判断时,运算的次数要少,在这个案例中少20%,也就是说节约了20%的算力,若是是线性的话,则提高了25%的性能.大数据

 

咱们反过来试一试,假设两个球都小于2的时候为中奖,分别按大小几率实验一下.优化

小几率spa

$times = 0;

//先判断小几率事件
for($i=1;$i<=10;$i++){
	for($j=1;$j<=10;$j++){
		if($i<=2 && $j<=2){
			$times += 3;
		}elseif($i<=2 && $j>2){
			$times += 6;
		}elseif($i>2 && $j<=2){
			$times += 7;
		}else{
			$times += 6;
		}
	}
}

echo $times; //496次判断

大几率code

$times = 0;
//先判断大几率事件
for($i=1;$i<=10;$i++){
	for($j=1;$j<=10;$j++){
		if($i>2 && $j>2){
			$times += 3;
		}elseif($i>2 && $j<=2){
			$times += 6;
		}elseif($i<=2 && $j<=2){
			$times += 7;
		}else{
			$times += 6;
		}
	}
}

echo $times; //412次判断

能够看到,从大几率开始判断仍然 比 从小几率开始判断 节省了算力,在这个案例中,节省了约19%.事件

 

可是,能够看出,不管是大几率仍是小几率,以2为分界线的运算量 比 以8为分界线的运算量更少.

412/496 vs. 424/652,虽然中奖几率都是同样的.这是个颇有意思的问题.

大概的缘由是,从一开始判断的顺序问题,由于数字是从1到10这样排列的,而下面的方法从小数字开始判断的,因此就很容易进入前面的分支,节约了一些算力.

 

思考:

1, 大几率;

2, 顺着数字变化的方向来判断---因此在指定获奖规则的时候能够参考顺着数字变化顺序来;

3, 逻辑或(还有 or die这种),逻辑与的短路问题,节约时间.

相关文章
相关标签/搜索