Как все время потерять копейки? - PullRequest
6 голосов
/ 02 августа 2011

Я буду работать в компании, где они программируют для финансовых учреждений, и я буду много работать с деньгами. Раньше это не было для меня большой проблемой, потому что я занимался мелкими деньгами, и в какой-то момент Дабла было достаточно, но теперь даже 1 копейка чертовски важна.

Я думаю, что каждый может знать

Dim mValue as Decimal = 100 'seems the best type for now
mValue = mValue / 3
Console.WriteLine(mValue)
Console.ReadLine()

mValue = mValue * 3
Console.WriteLine(mValue)
'Outputs 99.9999999999999999999999999... and never hits 100

Так, как я могу преодолеть эту проблему и найти еще более точные результаты?

Спасибо.

Ответы [ 5 ]

5 голосов
/ 02 августа 2011

Если вам нужно выполнить произвольное деление, похоже, вам нужно представление рационального числа (дроби).Я не верю, что .NET предоставляет один по умолчанию, и вам будет «весело» реализовывать его так, чтобы он работал так же хорошо, как и встроенные числовые типы.Это может побудить вас к сложению, вычитанию, умножению и делению, но это не поможет, если вам тоже нужны иррациональные числа (например, получение квадратных корней).

Вы уверены вы 'будет делить на 3, хотя?Вы уверены, что не можете округлить до (скажем) ближайшей 1000-й копейки?Вы должны выяснить, каковы точные требования к вашим расчетам - я сомневаюсь, что вам действительно нужно быть бесконечно точными.

4 голосов
/ 03 августа 2011

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

100 allocated by 3 = [ 33, 33, 34 ]

Кто-то должен получить эту лишнюю копейку.

Кроме того, проще использовать целое число, представляющее количество копеек, чем десятичное число.

И, инкапсулировать денежные операции - это отдельный класс. Взгляните на шаблон Money .

3 голосов
/ 02 августа 2011

Можете ли вы предложить мне пример использования в реальной жизни для этого?

mValue = mValue / 3

Делить $ 100 между тремя грабителями банков?
Ну, вы не можете дать $ 33. (3) каждому, $ 0,01 все равно придется идти "никуда" (если вы не хотите, чтобы они убивали друг друга).

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

2 голосов
/ 02 августа 2011

Я не эксперт в этой области, поэтому кто-то с большим опытом может ответить на этот вопрос лучше.

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

100/3 = 33,333333333333333 * 3 = 99,999999999999, который затем округляется до 100.

Я знаю, что многие вещи используют то, что называется округлением банкиров. Это сделано для того, чтобы предотвратить потерю денег, когда что-то заканчивается ровно 5. Он округляется, если число до 5 нечетное, и округляется, если число четное. Что-то, чтобы рассмотреть.

http://en.wikipedia.org/wiki/Rounding

0 голосов
/ 10 июня 2012

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

  old_total = total
  old_rounded_total = rounded_total
  total = total + line_item
  rounded_total = round_to_penny(total)
  displayed_line_item_cost = rounded_total - old_rounded_total

В других случаях можно округлить все строки счета-фактуры до ближайшего пенни, вычесть из этой суммы сумму всех не округленных строк счета-фактуры и скорректировать вверх или вниз те строки, которые были ближе всего к границе "пенни". 1004 *

Если семантика округления четко определена и приложение следует им, результаты будут точно соответствовать спецификации. Если семантика не четко определена, результаты также не будут.

...