私が構築しているプログラムのアカウンティングルーチンを作成する必要があります。これにより、小数を整数で均等に除算できます。たとえば、次のようになります。
$143.13 / 5 =
28.62
28.62
28.63
28.63
28.63
私はここで記事を見ました:c#で均等に除算しますが、整数除算でのみ機能するようです。この問題に対するエレガントな解決策のアイデアはありますか?
私が構築しているプログラムのアカウンティングルーチンを作成する必要があります。これにより、小数を整数で均等に除算できます。たとえば、次のようになります。
$143.13 / 5 =
28.62
28.62
28.63
28.63
28.63
私はここで記事を見ました:c#で均等に除算しますが、整数除算でのみ機能するようです。この問題に対するエレガントな解決策のアイデアはありますか?
一度に1つずつ金額を計算し、合計から各金額を差し引いて、常に正しい合計が残っていることを確認します。
decimal total = 143.13m;
int divider = 5;
while (divider > 0) {
decimal amount = Math.Round(total / divider, 2);
Console.WriteLine(amount);
total -= amount;
divider--;
}
結果:
28,63
28,62
28,63
28,62
28,63
配列を作成せずにこれを(セントで)解決できます。
int a = 100 * amount;
int low_value = a / n;
int high_value = low_value + 1;
int num_highs = a % n;
int num_lows = n - num_highs;
セントを扱う方が簡単です。143.13の代わりに、14313を5つの等しい部分に分割することをお勧めします。これにより、2862と残りの3が得られます。この残りを最初の3つの部分、または任意の方法に割り当てることができます。最後に、セントをドルに戻します。
また、必要なパーツの数よりも少ない残りが常に得られることに注意してください。
まず、ドルとセントを表すために浮動小数点数を使用しないようにしてください(理由については他の投稿を参照してください。ただし、単純な理由は、すべての10進数を浮動小数点数として表すことができないためです(例:$ 1.79))。
これを行う1つの方法は次のとおりです。
decimal total = 143.13m;
int numberOfEntries = 5;
decimal unadjustedEntryAmount = total / numberOfEntries;
decimal leftoverAmount = total - (unadjustedEntryAmount * numberOfEntries);
int numberOfPenniesToDistribute = leftoverAmount * 100;
int numberOfUnadjustedEntries = numberOfEntries - numberOfPenniesToDistribute;
これで、未調整の金額が28.62になり、残りをどのように分配するかを決定する必要があります。上または下から始めて、それぞれに追加のペニーを分配することができます(下から望むように見えます)。
for (int i = 0; i < numberOfUnadjustedEntries; i++) {
Console.WriteLine(unadjustedEntryAmount);
}
for (int i = 0; i < numberOfPenniesToDistribute; i++) {
Console.WriteLine(unadjustedEntryAmount + 0.01m);
}
残り全体を最初または最後のエントリに追加することもできます。最後に、会計上のニーズに応じて、残りのトランザクションを個別に作成することもできます。
正確に2桁の精度が保証されているフロートがある場合、これはどうでしょうか(擬似コード)。
amount = amount * 100 (convert to cents)
int[] amounts = new int[divisor]
for (i = 0; i < divisor; i++) amounts[i] = amount / divisor
extra = amount % divisor
for (i = 0; i < extra; i++) amounts[i]++
次にamounts
、セント単位で必要な操作を行います。どうしても必要な場合は、フロートに戻すか、ドルとセントでフォーマットすることができます。
明確でない場合、このすべてのポイントは、セントが米ドルの不可分な単位であることを考えると、フロート値を均等に分割するだけでなく、金額を可能な限り均等に分割することです。OPへ:これがあなたが望んでいたものではないかどうか私に知らせてください。
参照している質問のアルゴリズムを使用するには、100を乗算し、整数の均等除算関数を使用してから、各結果を100で除算します(3dpを1000で乗算する場合は、2dpのみを処理する必要があると想定します)。等)
C#イテレータ生成を使用して、Guffaの回答をより便利にすることもできます。
public static IEnumerable<decimal> Divide(decimal amount, int numBuckets)
{
while(numBuckets > 0)
{
// determine the next amount to return...
var partialAmount = Math.Round(amount / numBuckets, 2);
yield return partialAmount;
// reduce th remaining amount and #buckets
// to account for previously yielded values
amount -= partialAmount;
numBuckets--;
}
}