Распределение денег
От: Ed.Nixon  
Дата: 02.11.12 03:24
Оценка:
Здраствуйте,

Стоит задача — приходит сумма денег, ее надо раскидать 70% туда, 5% сюда и т.п.
Деньги приходят в usd/eur/rur (ну не суть наверное).
Язык C#, использую decimal везде.
В конце расчетов сумма прихода и расхода не совпадают.

В SQL Server хранится все с точностью (18,2) (может проблема в этом ?)

Подскажите как правильно работать в c# с деньгами.

Спасибо!
Re: Распределение денег
От: Mihas  
Дата: 02.11.12 04:22
Оценка:
Здравствуйте, Ed.Nixon, Вы писали:
Может быть, с округлением что-то не так? Сколько у тебя получается, если взять 5% от 99.99р?
Re: Распределение денег
От: Nikolay_P_I  
Дата: 02.11.12 05:25
Оценка: 12 (2) +1
EN>Стоит задача — приходит сумма денег, ее надо раскидать 70% туда, 5% сюда и т.п.
EN>Деньги приходят в usd/eur/rur (ну не суть наверное).
EN>Язык C#, использую decimal везде.
EN>В конце расчетов сумма прихода и расхода не совпадают.
EN>В SQL Server хранится все с точностью (18,2) (может проблема в этом ?)
EN>Подскажите как правильно работать в c# с деньгами.

Правильный ответ — "а сколько надо" ? Ну или "позвоните своему бухгалтеру". Потому как в реальной жизни из-за округления сумма у вас скорее всего принципиально сходиться не будет. Потому лучше узнайте как надо не с точки зрения математики и программирования, а с точки зрения предметной области.
Кстати, проверьте еще и округление — не факт, что оно в вашем языке программирования и базе данных именно банковское.

P.S. Когда-то я писал супер-программу для автобазы. В том числе на считала премии за экономию топлива. Алгоритм расчета очень круто считал с очень повышенной точностью, знаков 10 после запятой. Как-то я поинтересовался всей цепочкой — оказалось, что на входе данные от шофера, который смотрит на топливометр с точностью деления +-5 литров. После этого я перестал гоняться за математической правильностью и всегда сразу узнаю у заказчика — чего ему конкретно надо, в каком виде, с какой точностью, какие на то есть постановления и, главное — как это считают руками.
Re: Распределение денег
От: HowardLovekraft  
Дата: 02.11.12 06:40
Оценка:
Здравствуйте, Ed.Nixon, Вы писали:

EN>В конце расчетов сумма прихода и расхода не совпадают.

Decimal не избавляет от проблем с округлением:
            var total = 1000M;
            var partsCount = 13;
            var parts = new decimal[partsCount];

            for (var i = 0; i < partsCount; i++)
            {
                parts[i] = total / partsCount;
            };

            Console.WriteLine(parts.Sum()); // 999,9999999999999999999999999


EN>В SQL Server хранится все с точностью (18,2) (может проблема в этом ?)

Увеличить точность можно, сложнее объяснить бухгалтерии, как перечислить 100,34455566778899 копеек.

EN>Подскажите как правильно работать в c# с деньгами.

Зависит от ситуации. В вашем случае я бы поступил так:
            var total = 1000M;
            var partsCount = 13;
            var parts = new decimal[partsCount];

            for (var i = 0; i < partsCount - 1; i++)
            {
                parts[i] = total / partsCount;
            };

            parts[partsCount - 1] = total - parts.Take(partsCount - 1).Sum();

            Console.WriteLine(parts.Sum()); // 1000,0000000000000000000000000
Re[2]: Распределение денег
От: drol  
Дата: 02.11.12 18:59
Оценка:
Здравствуйте, Nikolay_P_I, Вы писали:

N_P>Кстати, проверьте еще и округление — не факт, что оно в вашем языке программирования и базе данных именно банковское.


У C#'ного decimal как раз banker's rounding. Ну как минимум в спецификации...
Re: Распределение денег
От: Flem1234  
Дата: 03.11.12 08:04
Оценка: 11 (1) +3
Здравствуйте, Ed.Nixon, Вы писали:
EN>Подскажите как правильно работать в c# с деньгами.

При работе с деньгами (если это бухгалтерия) важно чтобы выполнялся закон:
Сколько пришло столько и должно уйти.
Т.к. при делении элементарных типов (вроде decimal) возможны отклонения от этого закона (т.е. в результате сумма не равна частям) то вывод такой:
Деление нельзя использовать (в случае если не можешь доказать, что оно не создаст проблем).

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

Например: если надо поделить 13 копеек между 5 людьми, то каждому должно уйти

13 / 5 = 2 обязательно и возможно + 1 если он из тех счастивчиков между которыми (возможно) равномерно распределяется остаток. Итого ничего не исчезло, бухгалтер доволен.

На уровне реализации сам тип данных (класс) иметь не обязательно, по ситуации.
Re[2]: Распределение денег
От: Hex66 Россия  
Дата: 05.11.12 07:19
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Зависит от ситуации. В вашем случае я бы поступил так:

HL>
HL>            var total = 1000M;
HL>            var partsCount = 13;
HL>            var parts = new decimal[partsCount];

HL>            for (var i = 0; i < partsCount - 1; i++)
HL>            {
HL>                parts[i] = total / partsCount;
HL>            };

HL>            parts[partsCount - 1] = total - parts.Take(partsCount - 1).Sum();

HL>            Console.WriteLine(parts.Sum()); // 1000,0000000000000000000000000
HL>


Предложил бы дополнить: менять при каждой следующей операции куда прибавляется остаток.
Можно реализовать денежную операцию деления:
напр: 10 / 3 = 3,33 (сколько знаков оговорено бухгалтером)
Re: Распределение денег
От: victor_kr Украина  
Дата: 05.11.12 14:18
Оценка:
Здравствуйте, Ed.Nixon, Вы писали:

EN>Здраствуйте,


EN>Стоит задача — приходит сумма денег, ее надо раскидать 70% туда, 5% сюда и т.п.

EN>Деньги приходят в usd/eur/rur (ну не суть наверное).
EN>Язык C#, использую decimal везде.
EN>В конце расчетов сумма прихода и расхода не совпадают.

EN>В SQL Server хранится все с точностью (18,2) (может проблема в этом ?)


EN>Подскажите как правильно работать в c# с деньгами.


EN>Спасибо!


На практике встречал такое. Округляют до 4-х знаков после запятой. Последнюю сумму считают вычитанием предыдущих частей из целого. У бухгалтера/менеджера есть возможность вручную корректировать итоговые суммы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.