如何更优雅编码、更优算法 | 阶梯式电费算法

如何更优雅编码、更优算法 | 阶梯式电费算法

😁笑:-D~ 倒序进行中,如何更加优雅、使用更少的代码,甚至更优的算法呢?

常常会见到这种场景:

举个栗子,深圳为了推进市民节约用电推出了这样一个用电收费政策,电量使用阶梯式递增的收费计算方式,简单而言、用电越多平均的每度电越贵。(假设用户的每电量为整数,小于1度电则应缴费为0元)

计算电费的剃度表如下所示:

耗电范围(°) 电费计算(1元/°)
1<=x<=10 1
11<=x<=20 1.2
21<=x<=50 1.4
51<=x<=100 1.8
101<=x<=300 2.4
301<=x 5
  • 一般的算法如下。糟糕的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 根据用电的度数计算电费
* @param int $number 用电度数
* @return float 电费
*/
function calculate(int $number): float
{
if ($number <= 0) {
return 0;
}
switch ($number) {
case 1 <= $number && $number <= 10:
return $number * 1;
break;
case 11 <= $number && $number <= 20:
return ($number - 10) * 1.2 + calculate(10);
break;
case 21 <= $number && $number <= 50:
return ($number - 20) * 1.4 + calculate(20);
break;
case 51 <= $number && $number <= 100:
return ($number - 50) * 1.8 + calculate(50);
break;
case 101 <= $number && $number <= 300:
return ($number - 100) * 2.2 + calculate(100);
break;
default:
return ($number - 300) * 5 + calculate(300);
break;
}
}
  • 良好的算法代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    /**
    * 根据用电的度数计算电费
    * @param int $number 用电度数
    * @return float 电费
    */
    function calculate(int $useNum): float
    {
    if ($useNum < 1) {
    return 0;
    }
    // 电费价格及其范围的配置定义 | 此梯度可抽出来独立配置
    $degrees = [10, 20, 50, 100, 300];
    $prices = [1, 1.2, 1.4, 1.8, 2.4, 5];

    // 判断是否达到最贵的价格梯度并计算其价格
    $beyondNum = $useNum - end($degrees);
    $price = ($beyondNum >= 0 ? $beyondNum : 0) * end($prices);

    // 上一层价格峰值
    $prePeak = 0;
    foreach ($degrees as $key => $value) {
    if ($useNum <= $value) {
    $price += ($useNum - $prePeak) * $prices[$key];
    break;
    }
    $price += ($value - $prePeak) * $prices[$key];
    $prePeak = $value;
    }
    unset($degrees, $prices, $beyondNum, $prePeak);
    return $price;
    }
# PHP
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×