Является ли двойным действительно неподходящим для денег?
Я всегда говорю в c # переменная типа double не подходит для денег. Все странные вещи могут случиться. Но я не могу создать пример для демонстрации некоторых из этих проблем. Может ли кто-нибудь представить такой пример?
(edit; этот пост был первоначально отмечен C #; некоторые ответы относятся к конкретным деталям decimal
, что значит System.Decimal
).
(edit 2: Я задавал некоторый код c #, поэтому я не думаю, что это только агностик языка)
- Для чего нужен пузырь?
- Лучший способ найти точку на круге, ближайшем к данной точке
- Что такое lambda (функция)?
- Алгоритм для выделения перекрывающихся прямоугольников?
- Что такое непрозрачное значение в C ++?
Очень, очень непригодно. Используйте десятичное число.
double x = 3.65, y = 0.05, z = 3.7; Console.WriteLine((x + y) == z); // false
(пример с страницы Джона здесь – рекомендуемое чтение; -p)
Вы получите нечетные ошибки, вызванные округлением. Кроме того, сравнение с точными значениями чрезвычайно сложно – вам обычно нужно применить какой-то epsilon, чтобы проверить, что фактическое значение «близко» к определенному.
Вот конкретный пример:
using System; class Test { static void Main() { double x = 0.1; double y = x + x + x; Console.WriteLine(y == 0.3); // Prints False } }
Да, это непригодно.
Если я правильно помню, что double имеет около 17 значащих чисел, то обычно ошибки округления будут значительно отставать от десятичной точки. Большинство финансовых программ использует 4 десятичных знака за десятичной точкой, что позволяет работать с 13 десятичными знаками, поэтому максимальное число, с которым вы можете работать для отдельных операций, по-прежнему намного выше, чем государственный долг США. Но ошибки округления будут складываться со временем. Если ваше программное обеспечение работает в течение длительного времени, вы в конечном итоге начнете проигрывать центы. Определенные операции сделают это хуже. Например, добавление больших количеств в небольшие количества приведет к значительной потере точности.
Вам нужны фиксированные точечные типы данных для операций с деньгами, большинство людей не против, если вы теряете цент здесь и там, но бухгалтеры не похожи на большинство людей.
редактировать
Согласно этому сайту http://msdn.microsoft.com/en-us/library/678hzkk9.aspx У парного разряда на самом деле есть от 15 до 16 значащих цифр вместо 17.
@Jon Skeet decimal более подходит, чем двойной, из-за его высокой точности, 28 или 29 значительных десятичных знаков. Это означает, что становится меньше шансов на накопление ошибок округления. Фиксированные точечные типы данных (т. Е. Целые числа, которые представляют центы или 100-й процент, как я видел, используются), как упоминания Boojum, на самом деле лучше подходят.
Так как decimal
использует коэффициент масштабирования, кратный 10, цифры, как 0,1, могут быть представлены точно. По сути, десятичный тип представляет это как 1/10 ^ 1, тогда как double
будет представлять это как 104857/2 ^ 20 (на самом деле это будет больше похоже на действительно большое число / 2 ^ 1023).
decimal
цифра может точно представлять любое значение базы 10 с до 28/29 значащими цифрами (например, 0,1). double
не может.
Я понимаю, что большинство финансовых систем выражают валюту, используя целые числа, т. Е. Подсчитывая все в центах.
Фактически двойная точность IEEE может представлять все целые числа точно в диапазоне от -2 ^ 53 до + 2 ^ 53. (Hacker’s Delight, стр. 262). Если вы используете только сложение, вычитание и умножение и сохраняете все до целых чисел в этом диапазоне, то вы не увидите потери точности. Однако я бы очень опасался разделения или более сложных операций.
Использование double, когда вы не знаете, что вы делаете, непригодно.
«double» может представлять собой сумму в триллион долларов с ошибкой 1/90 процента. Таким образом, вы получите очень точные результаты. Хотите рассчитать, сколько стоит положить мужчину на Марс и вернуть его обратно? двойной будет делать только отлично.
Но с деньгами часто бывают очень конкретные правила, говорящие, что определенный расчет должен дать определенный результат, а другой нет. Если вы подсчитаете сумму, которая очень очень близка к 98,35 долларам, тогда часто будет правило, определяющее, должен ли результат быть $ 98.14 или $ 98.13, и вы должны следовать этому правилу и получить требуемый результат.
В зависимости от того, где вы живете, использование 64-битных целых чисел для представления центов, копейки или копейки или всего, что является наименьшей единицей в вашей стране, обычно будет работать нормально. Например, 64-битные знаковые целые числа, представляющие центы, могут представлять значения до 92 223 триллионов долларов. 32-битные целые числа обычно непригодны.
Нет двойника всегда будут ошибки округления, используйте «десятичный», если вы находитесь на .Net …
Фактически double – double с плавающей запятой отлично подходит для представления суммы денег, пока вы выбираете подходящую единицу.
См. http://www.idinews.com/moneyRep.html
Так долго фиксированная точка. Либо потребляет 8 байтов, что предпочтительнее 16, потребляемых десятичным элементом.
Независимо от того, работает ли что-то (т. Е. Дает ожидаемый и правильный результат), дело не в голосовании, а в индивидуальном предпочтении. Техника работает или нет.