Общие стратегии для устранения ошибок округления в валютно-мягкой программе? - PullRequest
8 голосов
/ 18 мая 2010

Ваш совет:

  1. компенсация накопленной ошибки в массовых математических операциях над коллекциями объектов Money. Как это реализовано в вашем рабочем коде для вашей локали?
  2. теория за округлением в бухгалтерии.
  3. любая литература по теме.

Я сейчас читаю Фаулер . Он упоминает тип денег, это типичная структура (int, long, BigDecimal), но ничего не говорит о стратегиях.

Более старые сообщения о округлении денег ( здесь и здесь ) не предоставляют подробности и формальность, которые мне нужны.

Мысли, которые я нашел в инете, относятся к "Половине четных" как к лучшему способу уравновесить ошибку.

Спасибо за помощь.

Ответы [ 6 ]

5 голосов
/ 19 мая 2010

При записи финансовых данных возникает много проблем с округлением. Первая проблема - это возможность хранить и извлекать точные десятичные числа

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

Если эта первая проблема решена, то никакое добавление (или вычитание) не может привести к ошибкам округления. То же самое касается умножения на целое число.

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

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

10.00  
-3.33  
-3.33  
-3.33  

и

-0.01 

(ошибка округления)

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

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

EDIT: Что касается ссылок на литературу, этот кажется интересным и не слишком длинным и касается довольно широкой аудитории с интересными сценариями.

4 голосов
/ 18 мая 2010

Никогда не храните денежные значения в двоичном или плавающем числах - используйте int или long, поскольку невозможно точно хранить 0,1 в двоичном виде.

3 голосов
/ 19 мая 2010

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

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

3 голосов
/ 18 мая 2010

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

http://www.xbeat.net/vbspeed/i_BankersRounding.htm

Вы можете расширить это, чтобы округлить toward ближайший два пенни вместо этого. Таким образом, 22,5 раунда до 22, но 23,5 раунда до 24, 23,1 и 22,9, оба раунда до 23. Однако алгоритм первоначального банкира более популярен.

1 голос
/ 19 мая 2010

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

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

1 голос
/ 19 мая 2010

Я немного (совсем немного) работал с денежными суммами, и мне было чрезвычайно любопытно, какая стратегия используется в моей компании ...

Оказывается, мы используем double, но они подумали об этом.

Дело в том, что суммы, с которыми мы имеем дело, не так уж велики (скажем, менее 10 КБ), и, самое большее, нам нужно 3 цифры после запятой, что в общей сложности составляет 7 значащих цифр.

Поскольку мы используем 64-битное программное обеспечение (и C ++), тип double предлагает достаточно значащие цифры для числа операций, которые мы выполняем:)

Если вам нужна большая точность, есть алгоритмы для использования (например, при добавлении нескольких денег), но лично я думаю, что суть проблемы заключается в:

  • конвертация из одной валюты в другую, которая постоянно меняется
  • проблемы с печатью: для некоторых денег не требуется десятичная дробь, для других - не более 2, и т. Д ...

Возможно, не могли бы вы рассказать о том, что вы делаете?

...