4

我有这个很长的方法:

public decimal decDiscount(QuoteData quoteData)
    {
        if (TotalChapter7(quoteData) >= 7499)
            return 5300;
        else if (TotalChapter7(quoteData) >= 7449)
            return 5300;
        else if (TotalChapter7(quoteData) >= 7399)
            return 5250;
        else if (TotalChapter7(quoteData) >= 7349)
            return 5200;
        else if (TotalChapter7(quoteData) >= 7299)
            return 5200;
        else if (TotalChapter7(quoteData) >= 7249)
            return 5150;
        else if (TotalChapter7(quoteData) >= 7199)
            return 5100;
        else if (TotalChapter7(quoteData) >= 7149)
            return 5100;
        else if (TotalChapter7(quoteData) >= 7099)
            return 5050;
            //...
        else if (TotalChapter7(quoteData) >= 1199)
            return 1100;
        else if (TotalChapter7(quoteData) >= 1149)
            return 1100;
        else if (TotalChapter7(quoteData) >= 1099)
            return 1050;
        else if (TotalChapter7(quoteData) >= 1049)
            return 1000;
        else
            return 0;
    }

它有一个反复出现的模式,可以用下面的 Excel 表来说明:

Excel 工作表第 1 部分 ……>>>> Excel 工作表第 2 部分

从最高的“费用”(7499)开始,每张报表的费用下降 50。但是,每 100 的回报(或“折扣价”)保持不变(两次 50 的费用下降),然后自己下降 50 以获得一次回报(一次 50 的费用下降),然后重复。

如您所见,我的方法很长(我在 7049 和 1249 之间遗漏了)。我能做些什么来缩短这个吗?

谢谢。

4

7 回答 7

3

你们真的太复杂了。任何试图使用整数算术解决这个问题的方法都是一个坏主意。看看一群真正聪明的人(我们都很聪明,不是吗?)甚至一开始就做对是多么困难。这真的很难发现,真的很难理解,很难正确,而且维护起来很糟糕。

您需要一种易于理解且易于维护的方法。查看您的原始帖子,您有该规则的英文描述。

但是,每 100 的回报(或“折扣价”)保持不变(两次 50 的费用下降),然后自己下降 50 以获得一次回报(一次 50 的费用下降),然后重复。

代码实际上是自己写的:

public int GetFeeFromQuoteData(QuoteData quoteData) {
    int fee = 5300;
    int difference = 7449 - TotalChapter7(quoteData);
    bool isTwoStep = true;

    while (difference > 0) {
        if (isTwoStep) {
            difference -= 50;
        }
        else {
            difference -= 100;
        }
        fee -= 50;
        isTwoStep = !isTwoStep;
    }
    return fee;
}
于 2012-05-29T16:27:26.550 回答
2

这些价格和折扣是数据!数据永远不应该被编译成代码

我不会在代码中构建下降,我会构建基础定价结构(它们很可能会随着价格下降而发生变化,但不太可能改变整体定价结构)。

我会在反映此结构的易于更改的位置(例如数据库、xml 文件)中显示价格和相关折扣。

public class Pricing
{
     private List<Tuple<decimal, decimal>> pricePoints= new List<Tuple<int, decimal>> discountRanges();

    public Pricing()
    {
        // These hard coded values would be replaced by logic to load from file.
        pricePoints.Add(Tuple.Create(7499, 5300));
        pricePoints.Add(Tuple.Create(7399, 5250));
        pricePoints.Add(Tuple.Create(7349, 5200));
        pricePoints.Add(Tuple.Create(7249, 5150));
        . . .
        pricePoints.Add(Tuple.Create(1049, 1000));
    }

    public decimal GetDiscount(QuoteData quoteData)
    {
        var price = TotalChapter7(quoteData);
        foreach(var point in pricePoints)
        {
            if(price >= point.Item1)
                return point.Item2;
        }
        // If we're here it implies there were no matching points
        return 0;
    }
}

如果你在代码中构建了drop,并且他们改变了drop,你就必须改变代码。
将数据放入文件中,在运行时加载文件一次,他们可以更改价格,您只需要更改文件。

反驳“这显然是一个商业规则”评论

不包括销售点的折扣(一次优惠 2 次,此商品 10% 的折扣等),基本上有三种方法可以计算总体费用或费用的折扣(其中任何一种都可以与首选客户折扣相结合)。

  • 固定百分比(例如,始终为 10%)
  • 不同价格点的不同百分比。
  • 不同价格点的不同固定价格(这是我们在问题中看到的)

客户决定使用哪一个(或多个)是业务规则,是的,该规则需要在代码中表示。

但是,无论使用哪个规则,实际值都是数据,并且该数据永远不应该(除非非常特殊的情况)在代码中。

于 2012-05-29T16:14:24.697 回答
1

也许这会有所帮助:

        List<Tuple<int, int>> _FeeToPrice = new List<Tuple<int, int>> { 
                new Tuple<int,int>(7499,5300),
                new Tuple<int,int>(7399,5250),
                            ...
                new Tuple<int,int>(1049,1000)
            };

        public decimal decDiscount(QuoteData quoteData)
        {
            var processedQuoteData = TotalChapter7(quoteData);
            var tuple = _FeeToPrice.FirstOrDefault(x => processedQuoteData >= x.Item1);
            if (tuple != null)
                return tuple.Item2;

            return 0;                           
        }

编辑: _FeeToPrice结构可以从文件或数据库或其他一些来源加载,这将允许更容易更正返回值

于 2012-05-29T16:14:23.563 回答
1

分析计算的工作公式如下:

int calcDiscount(int p)
{
  int s = (7500/50) - (p+1) / 50;
  int k = s / 3;
  int j = s % 3;

  return 5300 - 100*k - (j == 2 ? 50 : 0) 
}

工作测试用例(Java):

for (p = 7499; p >= 1000; p -= 50)
{
  System.out.println (p+ " " + calcDiscount(p));
}

解释:首先你找到当前价格从最大值(7499)下降多少步,然后你知道你必须每三步将折扣值下降 100,但如果你在当前三元组的最后一步,你必须将它下降一个额外50。

于 2012-05-29T16:15:14.883 回答
0

伪代码如下:

Dictionary<Int, Int> getDiscounts(int startFee, int startDiscount, int endFee)
{
    Dictionary <Int, Int> quoteDictionary = new Dictionary<Int, Int> ();
    for(int i = 0; i++; startFee >= endFee)
    {
         startFee -= 50;
         if(i != 0)
         {
             startDiscount -= 50;
         }
         if(i == 2)
         {
             i = -1;
         }
         quoteDictionary[startFee] = startDiscount;
    }
    return quoteDictionary;
}

你可以这样称呼它:

Dictionary <Int, Int> prices = getDiscounts(7499, 5300, 1049);
int quote = TotalChapter7(quoteData);
int roundedQuote = quote - ((quote % 50) + 1);
int discountedFee = prices[roundedQuote];
于 2012-05-29T16:13:03.317 回答
0

我不知道这是否对您有用,但您可以使用字典,并按照上面的示例按降序对键进行排序。

我还没有测试过,但这样的事情可能会奏效:

public int GetNumber(int value)
{
    //initialize a dictionary to hold pairs of numbers
    var ranges = new SortedDictionary<int, int>
    {
        { 25, 250 },
        { 50, 500 },
        { 75, 750 }
    };

    //sort the dictionary in descending order and return the first value
    //that satisfies the condition
    return ranges.OrderByDescending(p => p.Key)
        .FirstOrDefault(p => value >= p.Key).Value;
}
于 2012-05-29T16:58:59.470 回答
-1

尝试使用字典,尝试做一个例子,但我不经常使用 C#,所以纠正代码上的任何不正确的地方,试着理解一下:

public decimal decDiscount(QuoteData quoteData)
{
    int result = 0; //if it doesn't match to any value on the dictionary it will return 0
    Dictionary<int, int> quotes = new Dictionary<int, int();
    quotes.add(7499, 5300); // not sure if that's how you add values to a dictionary
    ...
    quotes.add(1049, 1000);

    for(Entry<int, int> element in quotes) //not sure about the enhanced for too hehehe, not using C# for a while
    {
        if(TotalChapter7(quoteData) >= element.key() && element.value > result)
        {
            result = element.value(); //don't break cause you have to test the entire list for acurracy
        }
    }

    return result;
}
于 2012-05-29T16:11:20.837 回答