В настоящее время я работаю над проектом, связанным с фондовым рынком, использующим c ++, включающим много типов с плавающей точкой, таких как цены и индексы.
Я много читаю, говорит, что вы должны использовать десятичную дробь в денежной арифметике.
Почему бы не использовать Double или Float для представления валюты?
Разница между десятичной, плавающей и двойной в .NET?
Насколько я понимаю, разница между float и decimal float заключается в том, на какой основе интерпретируется экспоненциальная часть, использование float 2 в качестве базового и десятичного float 10. Когда вы используете десятичное float, вы все равно получаете ошибки округления, вы все равно не можете выразить 1/3 (поправьте меня, если я ошибаюсь), я думаю, вполне возможно умножить чей-то баланс на счете на 30%, и тогда возникает ошибка округления, после еще нескольких вычислений ошибка округления может распространиться еще серьезнее. Помимо большего диапазона чисел, почему я должен использовать десятичную дробь в финансовой арифметике?
В зависимости от того, какие финансовые операции вы выполняете, ошибки округления могут быть неизбежны. Если товар стоит 1,50 доллара США с 7% налогом с продаж, с вас не будет взиматься плата в размере 1,605 долларов США; цена, которую вы заплатите, будет $ 1.60 или $ 1.61. (Единицы валюты США теоретически включают «миллы», или тысячные доли доллара, но наименьшая монета достоинством 0,01 доллара, и почти все транзакции округляются до ближайшего цента.)
Если вы делаете простые вычисления (просто складываете и вычитаете количества и умножаете их на целые числа), все результаты будут целыми числами центов. Если вы используете двоичные числа с плавающей запятой, представляющие количество долларов, большинство сумм не будет представлено; расчет, который должен дать 0,01 доллара, может дать 0,01000000000000000020816681711721685132943093776702880859375.
Вы можете избежать этой проблемы, используя целые числа для представления количества центов (или, эквивалентно, используя фиксированную точку, если язык поддерживает это), или используя десятичную с плавающей точкой, которая может точно представлять 0,01.
Но для более сложных операций, таких как вычисление 7% налога с продаж, деление суммы денег на 3 равные части или, особенно, сложного процента, все еще будут результаты, которые не будут точно представлены, если вы не используете пакет произвольной точности, такой как GMP.
Насколько я понимаю, есть законы и правила, которые определяют именно так как ошибки округления должны быть решены. Если вы применяете 7% налог с продаж к 1,50 долл. США, вы не можете легально выбирать между 1,60 и 1,61 долл. США; закон говорит вам, какой из них является юридически правильным.
Если вы пишете финансовое программное обеспечение, которое будет использоваться другими людьми, вам необходимо точно знать, что говорится в правилах. Зная это, вы можете определить, какое представление (целые числа, с фиксированной запятой, десятичной с плавающей запятой или что-либо еще) лучше всего использовать для получения юридически требуемых результатов.
(Отказ от ответственности: я не знаю, что на самом деле говорится в этих правилах.)
По крайней мере, в США большинство компаний финансового типа обязаны использовать десятичную математику. Мейнфреймы со времен IBM 360 могут выполнять математику для строк переменной длины с упакованным десятичным числом. Обычно используется некоторая форма чисел с фиксированной точкой, с установленным количеством цифр после десятичной точки. Языки высокого уровня, такие как Cobol, поддерживают упакованные (или распакованные) десятичные числа. В случае мэйнфреймов IBM существует много унаследованного кода сборки, который можно дополнить кодом Cobol, отчасти потому, что когда-то к определенным типам баз данных обращались через макросы в сборке (теперь это называется HLASM — сборка высокого уровня).