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 シートで説明できる繰り返しパターンがあります。

エクセルシート その1 ……>>>> エクセルシート その2

最高の「料金」(7499)から始めて、料金は明細書ごとに 50 減っています。ただし、返品 (または「割引価格」) は 100 (手数料の 50 ドロップ 2 回) ごとに同じままで、1 回の返品 (手数料の 50 ドロップ 1 回) で 50 自体がドロップされ、その後繰り返されます。

ご覧のとおり、私の方法はかなり長いです (7049 から 1249 の間で省略したもの)。これを短縮するためにできることはありますか?

ありがとう。

4

7 に答える 7

3

皆さんはこれを非常に複雑にしています。整数演算を使用してこれを解決しようとするアプローチは、悪い考えです。本当に賢い人たちの集まり (私たちはみんな本当に賢いですよね?) にとって、そもそもそれを正しく理解することさえどれほど難しいか見てください。発見するのも、理解するのも、理解するのも、正しくするのも、維持するのも大変です。

理解しやすく、維持しやすいアプローチが必要です。元の投稿を見てください。ルールの英語の説明があります。

ただし、返品 (または「割引価格」) は 100 (手数料の 50 ドロップ 2 回) ごとに同じままで、1 回の返品 (手数料の 50 ドロップ 1 回) で 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;
    }
}

ドロップをコードに組み込み、それらがドロップを変更する場合は、コードを変更する必要があります。
データをファイルに入れ、実行時に一度ファイルをロードすると、価格が変更される可能性があり、ファイルを変更するだけで済みます。

「ここは明らかにビジネスルール」コメントへの反論

販売時点での割引 (1 つのオファーに対して 2 つ、このアイテムの 10% オフなど) を除いて、基本的に 3 つの方法で全体的な料金または手数料の割引を計算できます (いずれも優先顧客割引と組み合わせることができます)。

  • 固定パーセンテージ (例: 常に 10%)
  • 価格帯ごとに異なるパーセンテージ。
  • さまざまな価格帯に対するさまざまな定額料金 (これは質問に表示されているものです)

顧客が使用することを決定したのはビジネス ルールであり、そのルールをコードで表す必要があります。

ただし、どのルールが使用されるかに関係なく、実際の値はデータであり、そのデータは(非常に例外的な状況でない限り) コード内にあるべきではありません。

于 2012-05-29T16:14:24.697 に答える
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) からのドロップ ステップの数を見つけます。次に、割引値を 3 ステップごとに 100 ずつドロップする必要があることがわかりますが、現在のトリプレットの最後のステップにいる場合は、それを追加の 50。

于 2012-05-29T16:15:14.883 に答える
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 に答える
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 に答える
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 に答える
-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 に答える