如何更优雅编码、更优算法 | 阶梯式电费算法 | 非常感谢、请指教~

如何更优雅编码、更优算法 | 阶梯式电费算法 | 非常感谢、请指教~

电费的阶梯式算法

?笑:-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       
  • 一般的算法如下。感谢更优的代码方案~
/**
 * 根据用电的度数计算电费
 * @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;
    }
}

不定维数组的排序(键名)

如何优雅高效地将一个不定维数组按照键名排序。

// 如下为不定维数组变量
$data = [
    'amount'    => 100,
    'quota'     => 100000000,
    'applicant' => [
        'name'        => 'alicfeng',
        'sex'         => 'M',
        'age'         => 21,
        'certificate' => [
            'number'     => '441701995********',
            'start_date' => '20080808',
            'end_date'   => '20280808'
        ]
    ],
    'family'    => [
        'number' => 5,
        'feel'   => 'nice'
    ]
];
本作品采用《CC 协议》,转载必须注明作者和本文链接
价值源于技术,贡献源于分享 | 笔记分享归档 No matter where I am, I will reply you immediately when I see the email. My Email: echo "YUBzYW1lZ28uY29tCg==" | base64 -d 个人比较喜欢分享,若有不对的地方非常感谢指出 相互学习、共同进步~
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 8

没有看明白,传300进去,不是一直死循环?

5年前 评论

@半人间

 case 101 <= $number && $number <= 300:
            return ($number - 100) * 2.2 + calculate(100);
            break;

300的话、在此code往上递归,不会造成死循环

5年前 评论
ruke

一般这种区间的计算我都会使用foreach, 习惯问题, 我也不知道啥更优解, 下面是我的代码

function getPrice($useNum)
{
    if ($useNum < 1) {
        return 0;
    }
    $nums = [10, 20, 50, 100, 300];
    $prices = [1, 1.2, 1.4, 1.8, 2.4, 5];
    $exceptNum = $useNum - end($nums);
    $retMoney = ($exceptNum > 0 ? $exceptNum : 0) * end($prices);
    $except = 0;
    foreach ($nums as $key => $num) {
        if ($useNum <= $num) {
            $retMoney += ($useNum - $except) * $prices[$key];
            return $retMoney;
        } else {
            $retMoney += ($num - $except) * $prices[$key];
        }
        $except = $num;
    }

    return $retMoney;
}
5年前 评论

@ruke 很不错 :+1:,既简洁又高效~学习了、非常感谢!

5年前 评论
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;
}
5年前 评论

感觉遇到了同一份笔试题。。。我switch中后边加的是上一节的最大值 :joy:

5年前 评论

@Mr_WhiteDT 笔试竟然考这道题了O(∩∩)O哈哈~。 无论是使用if还是switch会造成时间复杂度很大,同时也导致代码灵活性不强。

5年前 评论

利用PHP_INT_MAX

function calculate(int $number): float
{
    $ranges = [0, 10, 20, 50, 100, 300, PHP_INT_MAX];
    $prices = [1, 1.2, 1.4, 1.8, 2.4, 5];
    $price = 0;
    for ($i = 1, $rLen = count($ranges); $i < $rLen; $i++) {
        if ($number > $ranges[$i]) {
            $price += ($ranges[$i] - $ranges[$i - 1]) * $prices[$i - 1];
        } else {
            $prices += ($number - $ranges[$i - 1]) * $prices[$i - 1];
            break;
        }
    }

    return $price;
}

不用PHP_INT_MAX

function calculate(int $number): float
{
    $ranges = [0, 10, 20, 50, 100, 300, 300];
    $prices = [1, 1.2, 1.4, 1.8, 2.4, 5];
    $price = 0;
    for ($i = 1, $rLen = count($ranges); $i < $rLen; $i++) {
        if ($number > $ranges[$i]) {
            $price += ($ranges[$i] - $ranges[$i - 1]) * $prices[$i - 1];
        } else {
            $prices += ($number - $ranges[$i - 1]) * $prices[$i - 1];
            break;
        }
    }

    return $price;
}
3年前 评论
Windysay 3年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!