Лучший способ хранить валютные значения в C ++ - PullRequest
54 голосов
/ 29 сентября 2008

Я знаю, что число с плавающей запятой не подходит для хранения значений валюты из-за ошибок округления. Существует ли стандартный способ представления денег в C ++?

Я заглянул в библиотеку наддува и ничего не нашел по этому поводу. В Java кажется, что BigInteger - путь, но я не смог найти эквивалент в C ++. Я мог бы написать свой собственный класс денег, но предпочел бы не делать этого, если что-то проверено.

Ответы [ 19 ]

2 голосов
/ 29 сентября 2008

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

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

1 голос
/ 15 октября 2014

Решение простое, хранить с любой требуемой точностью в виде сдвинутого целого числа. Но при чтении в конвертировать в двойное число с плавающей запятой, чтобы при вычислениях было меньше ошибок округления. Затем при хранении в базе данных умножьте на любую целочисленную точность, но перед усечением в виде целого числа добавьте +/- 1/10 для компенсации ошибок усечения или +/- 51/100 для округления. Легкий горох.

1 голос
/ 29 сентября 2008

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

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

(Другой пример, где это встречается, это проценты. Никогда не называйте значение «XXX_percent», когда оно фактически содержит отношение, не умноженное на сотню.)

0 голосов
/ 29 сентября 2008

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

0 голосов
/ 22 июля 2016

Я бы использовал подписанный long для 32-битных и подписанный long для 64-битных. Это даст вам максимальную емкость для самого базового количества. Затем я бы разработал два пользовательских манипулятора. Тот, который конвертирует это количество на основе обменных курсов, и тот, который форматирует это количество в выбранную вами валюту. Вы можете разработать больше манипуляторов для различных финансовых операций / и правил.

0 голосов
/ 15 марта 2016

Храните сумму в долларах и центах как два отдельных целых числа.

0 голосов
/ 29 сентября 2008

Библиотека GMP имеет реализации "bignum", которые можно использовать для целочисленных вычислений произвольного размера, необходимых для работы с деньгами. См. Документацию для mpz_class (предупреждение: это ужасно неполно, хотя предоставляется полный спектр арифметических операторов) .

0 голосов
/ 29 сентября 2008

вперёд, напишите свои собственные деньги (http://junit.sourceforge.net/doc/testinfected/testing.htm) или класс currency () (в зависимости от того, что вам нужно) и протестируйте их.

0 голосов
/ 29 сентября 2008

Один из вариантов - сохранить $ 10.01 как 1001 и выполнить все вычисления в копейках, разделив их на 100D при отображении значений.

Или используйте поплавки и только в последний момент.

Часто проблемы могут быть смягчены путем изменения порядка операций.

Вместо значения * .10 для скидки 10% используйте (значение * 10) / 100, что поможет значительно. (помните .1 повторяющийся двоичный файл)

...