2016-11-13 13 views
1

제가 일하고있는 프로그램의 일부는 패키지 무게를 인수로 취하고 그 무게에 따라 운송비를 계산하는 함수를 구현합니다. 다음과 같이 비용/파운드의 기준은 다음과 같습니다C++ 무게를 기준으로 운송비 계산하기

내가 사용
 Package Weight    Cost 
     --------------    ---- 
     25 lbs & under    $5.00 (flat rate) 
     26 - 50 lbs     above rate + 0.10/lb over 25 
     50 + lbs     above rate + 0.07/lb over 50 

는 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; 

그래서, 문제는 ...이 작업을 수행하는 가장 좋은 방법입니까 아니면 다른 솔루션을 찾아야합니까?

+3

당신이 가지고있는 것은 좋은 습관의면에서 뽀얀입니다. if-else if-else의 사용과 관련하여 반복되는 것은 없습니다. – VHS

+0

또한 여기에는 재귀적인 것이 없습니다. –

+0

이것이 유일한 계층이라고 가정하면이 부분이 정상적으로 보입니다. – Qix

답변

2

처음에는 코드가 분명하고 괜찮습니다. 물론

, 당신이 누적 접근 방식을 사용하여 식의 중복 부분을 중복 제거 수 :

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); 
} 

글쎄,이 더욱 단순화 할 수있다 : 3 저울

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; 

는, 그것의 아마이 합성 공식으로 괜찮아. 그러나 더 많은 유연성을 원한다면 상수를 사용하는 대신 속도의 벡터를 반복하는 것을 생각할 수 있습니다. 이것은 다양한 비늘 수를 허용합니다. 수식이 항상 프로그레시브 (예 : "+ 앞당겨지는 것에 대한 새로운 단가") 인 경우 누적 접근 방식을 사용하십시오.

+0

피드백을 보내 주셔서 감사합니다! 이것은 내가 염두에두고있는 것 이상의 것이지만 그것을 통해 생각할 수 없습니다. 매우 감사! – jslice

+0

귀하의 솔루션이 단순화되는 동안 효율성을 위해 어떤 상쇄 관계가 있습니까? 처음에는 하나의 비교 작업을 덜 사용한 다음 원본을 사용하지만 마지막에 게시 한 사람은 몇 분/최대를 사용합니다. 속도 진행이 더 큰 규모로 진행되면 차이가 있습니까? – jslice

+0

당신은 정말로 옳았지 만, 그것은 크게 옵티 마이저에 달려 있습니다. 예를 들어, GCC 6.2의 경우 [내 제안] (https://godbolt.org/g/pPQCgO)은 [원본 코드] (https://godbolt.org/g/sbkze7)보다 적은 asm 명령어입니다. 그리고 내 [ultraslim 기능] (https://godbolt.org/g/x3wxeA)은 4 가지 더 많은 지시 사항입니다. 그러나 전반적인 실행 성능은 명령 수뿐만 아니라 가중치의 통계적 분포 (점프가 더 많거나 적게 필요함)에 따라 달라집니다. 그러므로 "조기 최적화는 모든 악의 뿌리입니다." – Christophe

0

코드에는 거의 동일한 줄이 많이 있지만 실제 중복은 없다고 생각합니다. 더 많은 요율을 추가하면 잘못된 매크로 정의를 쉽게 복사하거나 잘못된 요율의 값을 혼합 할 수 있습니다.

내 코드 자체가 if/else 복제를 제거하고 정확한 전역 정의를 사용하지 않아도됩니다. 코드에 새 요율을 추가하면 테이블에 원시를 추가하기 만하면됩니다. C++ 11을 사용할 수없는 경우

#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); 
} 

, 당신은 또한 정상적인 기능 및 함수 포인터 대신 람다 및 표준 : 기능을 사용할 수 있습니다 :

만 할 수있는 다른 어떤 아이디어를 제공합니다.