【TDD】一道简单的算法题

本周是一道简单的算法题,计算利润。我计划使用TDD的原则开发,并且换用几种不同的方法解题。

如果你没看过上一期关于TDD和gtest的文章,我推荐你去看一下地址

题目:奖金计算

题目:

企业发放的奖金根据利润提成。利润低于或等于100000元的,奖金可提10%;


利润高于100000元,低于200000元(100000<I≤200000)时,低于100000元的部分按10%提成,高于100000元的部分,可提成 7.5%;


200000<I≤400000时,低于200000元部分仍按上述办法提成,(下同),高于200000元的部分按5%提成;


400000<I≤600000元时,高于400000元的部分按3%提成;



600000<I≤1000000时,高于600000元的部分按1.5%提成;


I>1000000时,超过1000000元的部分按1%提成。

方法一:if多else if

应该是最常规的一种解法。

依然按照之前文章的结构,搭建gtest环境,各部分的代码如下:

BonusMoney.h代码如下:

int bonus(int moneyGet);

BonusMoney.cpp代码如下:

#include "BonusMoney.h"

int bonus(int moneyGet)
{
    
    
    int bonus = 0;
    if (moneyGet <= 100000)
        bonus = 0.1 * moneyGet;
    else if (moneyGet <= 200000)
        bonus = 0.1 * 100000 + 0.075 * (moneyGet - 100000);
    else if (moneyGet <= 400000)
        bonus = 0.1 * 100000 + 0.075 * 100000 + 0.05 * (moneyGet - 200000);
    else if (moneyGet <= 600000)
        bonus = 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * (moneyGet - 400000);
    else if (moneyGet <= 1000000)
        bonus = 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * 200000 + 0.015 * (moneyGet - 600000);
    else
        bonus = 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * 200000 + 0.015 * 400000 + 0.01 * (moneyGet - 1000000);
    return bonus;
}

BonusMoney_unittest.cpp代码如下:

#include "gtest/gtest.h"
#include "BonusMoney.h"

TEST(bonusMoneyTest, moneyGet_10000)
{
    
    
    EXPECT_EQ(bonus(10000), 0.1 * 10000);
}

TEST(bonusMoneyTest, moneyGet_110000)
{
    
    
    EXPECT_EQ(bonus(110000), 0.1 * 100000 + 0.075 * (110000 - 100000));
}

TEST(bonusMoneyTest, moneyGet_210000)
{
    
    
    EXPECT_EQ(bonus(210000), 0.1 * 100000 + 0.075 * 100000 + 0.05 * (210000 - 200000));
}

TEST(bonusMoneyTest, moneyGet_410000)
{
    
    
    EXPECT_EQ(bonus(410000), 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * (410000 - 400000));
}

TEST(bonusMoneyTest, moneyGet_610000)
{
    
    
    EXPECT_EQ(bonus(610000), 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * 200000 + 0.015 * (610000 - 600000));
}

TEST(bonusMoneyTest, moneyGet_1100000)
{
    
    
    EXPECT_EQ(bonus(1100000), 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * 200000 + 0.015 * 400000 + 0.01 * (1100000 - 1000000));
}

int main(int argc, char **argv)
{
    
    
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

方法二:switch-case

在讲这个方法的原理前,我先介绍一个switch-case的特殊用法,也许不那么特殊。

一般来说,Switch-case结构,每个case中的代码都会以break结尾,代表跳出switch

switch(...):
	case a:
		...;
		break;
	case b:
		... ...

如果不使用break的话,会继续按顺序执行别的case中的代码,直到遇到下一个break。这种现象叫穿透。我一直以为,穿透是一种需要避免的bug,但其实,它也是一种可以利用的特性。

由于穿透会执行匹配到的case后面所有的工作代码,我们可以逆向思维,从最大的情况开始匹配,最大是无限大,所以将最大的匹配放在default里;同时,为了确保范围内的数都能得到匹配(毕竟我们不能每个数都写case),我们使用/进行范围转换:

switch (moneyGet / 100000)
    {
    
    
    default:
        moneyGet -= 1000000;
        profit += moneyGet * 0.01;
        moneyGet = 1000000;

减去每个范围的利润,并累加奖金。后面就是逐个穿透了:

	case 9:
    case 8:
    case 7:
    case 6:
        moneyGet -= 600000;
        profit += moneyGet * 0.015;
        moneyGet = 600000;

BonusMoneySwitch.cpp完整代码如下:

int bonusSwitch(int moneyGet)
{
    
    
    int profit = 0;
    switch (moneyGet / 100000)
    {
    
    
    default:
        moneyGet -= 1000000;
        profit += moneyGet * 0.01;
        moneyGet = 1000000;
    case 9:
    case 8:
    case 7:
    case 6:
        moneyGet -= 600000;
        profit += moneyGet * 0.015;
        moneyGet = 600000;
    case 5:
    case 4:
        moneyGet -= 400000;
        profit += moneyGet * 0.03;
        moneyGet = 400000;
    case 3:
    case 2:
        moneyGet -= 200000;
        profit += moneyGet * 0.05;
        moneyGet = 200000;
    case 1:
        moneyGet -= 100000;
        profit += moneyGet * 0.075;
        moneyGet = 100000;
    case 0:
        profit += moneyGet * 0.1;
    }
    return profit;
}

对应的gtest就不全写了,仅展示一例:

TEST(bonusMoneyTest, moneyGet_1100000)
{
    
    
    EXPECT_EQ(bonus(1100000), 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * 200000 + 0.015 * 400000 + 0.01 * (1100000 - 1000000));
    EXPECT_EQ(bonusSwitch(1100000), 0.1 * 100000 + 0.075 * 100000 + 0.05 * 200000 + 0.03 * 200000 + 0.015 * 400000 + 0.01 * (1100000 - 1000000));
}

当然,这道题用正向的switch-case也可以做,不过与if-else结构差不多。

其他解法

待补充,这周出去聚餐,太累了,文章有点水,见谅。

猜你喜欢

转载自blog.csdn.net/qq_37387199/article/details/127720070