Равномерно разделить сумму в долларах (десятичную) на целое число - PullRequest
16 голосов
/ 11 января 2010

Мне нужно написать программу учета для создаваемой мной программы, которая даст мне четное деление десятичного числа на целое число. Так что например:

$143.13 / 5 =

28.62
28.62
28.63
28.63
28.63

Я видел статью здесь: Равномерно делим на c # , но похоже, что это работает только для целочисленных делений. Есть идеи элегантного решения этой проблемы?

Ответы [ 7 ]

33 голосов
/ 11 января 2010

Рассчитайте суммы по одному и вычтите каждую сумму из общей суммы, чтобы убедиться, что у вас всегда есть правильная общая сумма:

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
29 голосов
/ 11 января 2010

Вы можете решить это (в центах), не создавая массив:

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;
3 голосов
/ 11 января 2010

Прежде всего, убедитесь, что вы не используете число с плавающей запятой для представления долларов и центов (см. Другие сообщения, почему, но простая причина в том, что не все десятичные числа могут быть представлены как числа с плавающей запятой, например, $ 1,79) .

Вот один из способов сделать это:

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

Вы также можете добавить весь остаток к первой или последней записи. Наконец, в зависимости от потребностей бухгалтерского учета, вы можете также создать отдельную транзакцию для остатка.

3 голосов
/ 11 января 2010

С центами легче иметь дело. Я бы предложил вместо 143,13 разделить 14313 на 5 равных частей. Это дает вам 2862 и остаток 3. Вы можете назначить этот остаток на первые три части или любым другим способом. Наконец, конвертируйте центы обратно в доллары.

Также обратите внимание, что вы всегда будете получать остаток меньше, чем количество частей, которые вы хотите.

2 голосов
/ 11 января 2010

Если у вас есть число с плавающей точкой, точность которого гарантируется ровно двумя цифрами, как насчет этого (псевдокод):

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, которые указаны в центах - вы можете конвертировать обратно в числа с плавающей точкой, если вам это абсолютно необходимо, или форматировать в долларах и центах.

Если не ясно, смысл всего этого не в том, чтобы делить плавающую стоимость равномерно, а в том, чтобы разделить денежную сумму как можно более равномерно, учитывая, что центы являются неделимой единицей доллара США. К ОП: дайте мне знать, если это не то, что вы хотели.

1 голос
/ 11 января 2010

Можно также использовать генерацию итератора C #, чтобы сделать ответ Гуфы более удобным:

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--;
    }
}
1 голос
/ 11 января 2010

Вы можете использовать алгоритм в вопросе, на который вы ссылаетесь, умножив на 100, используя функцию целочисленного равномерного деления, а затем разделив каждый из результатов на 100 (при условии, что вы хотите обрабатывать только 2 dp, если вы хотите 3dp умножить на 1000 и т. д.)

...