C++根据重量计算运费

C++ Calculating shipping cost based on weight

我正在处理的程序的一部分实现了一个函数,该函数将包裹重量作为参数并根据该重量计算运费。 cost/lb的条件如下:

        Package Weight              Cost
        --------------              ----
        25 lbs & under              .00 (flat rate)
        26 - 50 lbs                 above rate + 0.10/lb over 25
        50 + lbs                    above rate + 0.07/lb over 50

我用了 if-if else-if 来计算,但感觉有点重复:

const int TIER_2_WEIGHT = 25;
const int TIER_3_WEIGHT = 50;

const float TIER_1_RATE = 5.00;
const float TIER_2_RATE = 0.10;
const float TIER_3_RATE = 0.07;

float shipPriceF;


if(shipWeightF <= TIER_2_WEIGHT)
{
    shipPriceF = TIER_1_RATE;
}
else if(shipWeightF <= TIER_3_WEIGHT)
{
    shipPriceF = ((shipWeightF - TIER_2_WEIGHT) * TIER_2_RATE) +
                   TIER_1_RATE;
}
else
{
    shipPriceF = ((shipWeightF - TIER_3_WEIGHT) * TIER_3_RATE)   +
                 ((TIER_3_WEIGHT - TIER_2_WEIGHT) * TIER_2_RATE) +
                   TIER_1_RATE;
}

return shipPriceF;

所以,问题是...这是完成此任务的最佳方法,还是我应该寻找其他解决方案?

首先,您的代码看起来很清晰而且没有问题。

当然,您可以使用累积方法对公式中的冗余部分进行重复数据删除:

float shipPriceF = TIER_1_RATE; // to be paid anyway

if (shipWeightF > TIER_2_WEIGHT) // add the tier 2 if necessary
{
    shipPriceF += (min(shipWeightF, TIER_3_WEIGHT) - TIER_2_WEIGHT) * TIER_2_RATE;
}
if(shipWeightF > TIER_3_WEIGHT)  // add the tier 3 if really necessary
{
    shipPriceF += (shipWeightF - TIER_3_WEIGHT) * TIER_3_RATE);
}

好吧,这甚至可以进一步简化:

float shipPriceF = TIER_1_RATE 
                     + max(min(shipWeightF,TIER_3_WEIGHT)-TIER_2_WEIGHT,0) * TIER_2_RATE 
                     + max(shipWeightF-TIER_3_WEIGHT,0) * TIER_3_RATE; 

对于3个音阶,这个合成公式大概没问题。但是,如果您想要更大的灵活性,您可以考虑迭代速率向量而不是使用常量。这将允许可变数量的比例。如果您确定公式始终是渐进的(例如 "above + new unit price for what's exceding"),请使用累积方法。

我认为代码中有很多几乎相同的行,但不是真正的重复行。如果您添加更多汇率,您很容易复制错误的宏定义或混合错误汇率的值。

我的代码本身删除了 if/else 复制,避免了使用正确的全局定义的需要。如果您向我的代码添加新汇率,您只需向 table.

添加原始汇率

只是想知道还能做什么:

#include <iostream>
#include <functional>
#include <limits>

// first we define a entry of a table. This table contains the limit to which the ratio is valid and
// a function which calculates the price for that part of the weight.
struct RateTableEntry
{
    double max;
    std::function<double(double, double)> func;
};

// only to shrink the table width :-)
constexpr double MAX = std::numeric_limits<double>::max();

// and we define a table with the limits and the functions which calculates the price
RateTableEntry table[]=
{
    // first is flate rate up to 25
    {   25, [](double    , double       )->double{ double ret=                      5.00; return ret; }},
    // next we have up to 50 the rate of 0.10 ( use min to get only the weight up to next limit
    {   50, [](double max, double weight)->double{ double ret= std::min(weight,max)*0.10; return ret; }},
    // the same for next ratio. std::min not used, bedause it is the last entry
    {  MAX, [](double    , double weight)->double{ double ret=          weight     *0.07; return ret; }}
};

double CalcRate(double weight)
{
    std::cout << "Price for " << weight;
    double price = 0;
    double offset = 0;
    for ( auto& step: table )
    {
        // call each step, until there is no weight which must be calculated
        price+=step.func(step.max- offset, weight);
        // reduce the weight for that amount which allready is charged for
        weight-=step.max-offset;
        // make the table more readable, if not used this way, we have no max values but amount per step value
        offset+=step.max;
        if ( weight <= 0 ) break;   // stop if all the weight was paid for
    }

    std::cout << " is " << price << std::endl;

    return price;
}

int main()
{
    CalcRate( 10 );
    CalcRate( 26 );
    CalcRate( 50 );
    CalcRate( 51 );
    CalcRate( 52 );
    CalcRate( 53 );
}

如果 C++11 不可用,您也可以使用普通函数和函数指针代替 lambda 和 std::function。