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。
我正在处理的程序的一部分实现了一个函数,该函数将包裹重量作为参数并根据该重量计算运费。 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。