Является ли двойным действительно неподходящим для денег?

Я всегда говорю в С# переменная типа double не подходит для денег. Все странные вещи могут случиться. Но я не могу создать пример для демонстрации некоторых из этих проблем. Может ли кто-нибудь представить такой пример?

(edit; этот пост был первоначально помечен С#; некоторые ответы относятся к конкретным деталям decimal, что означает System.Decimal).

(отредактируйте 2: я задавал некоторый код С#, поэтому я не думаю, что это только агностик языка)

Ответ 1

Очень, очень непригодно. Используйте десятичное число.

double x = 3.65, y = 0.05, z = 3.7;
Console.WriteLine((x + y) == z); // false

(пример из страницы Jon < здесь - рекомендуемое чтение; -p)

Ответ 2

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

Вот конкретный пример:

using System;

class Test
{
    static void Main()
    {
        double x = 0.1;
        double y = x + x + x;
        Console.WriteLine(y == 0.3); // Prints False
    }
}

Ответ 3

Да, это неприемлемо.

Если я правильно помню, что double имеет около 17 значащих чисел, то обычно ошибки округления будут значительно отставать от десятичной точки. Большинство финансовых программ использует 4 десятичных знака за десятичной точкой, что позволяет работать с 13 десятичными знаками, поэтому максимальное число, с которым вы можете работать для отдельных операций, по-прежнему намного выше, чем государственный долг США. Но ошибки округления будут складываться со временем. Если ваше программное обеспечение работает в течение длительного времени, вы в конечном итоге начнете проигрывать центы. Определенные операции сделают это хуже. Например, добавление больших количеств в небольшие количества приведет к значительной потере точности.

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

изменить
Согласно этому сайту http://msdn.microsoft.com/en-us/library/678hzkk9.aspx У удвоений на самом деле есть от 15 до 16 значащих цифр вместо 17.

@Jon Skeet decimal более подходит, чем двойной, из-за его более высокой точности, 28 или 29 значащих десятичных знаков. Это означает, что становится меньше шансов на накопление ошибок округления. Фиксированные точечные типы данных (т.е. Целые числа, которые представляют центы или 100-й процент, как я видел, используются), как упоминания Boojum, на самом деле лучше подходят.

Ответ 4

Так как decimal использует коэффициент масштабирования кратных 10, числа, подобные 0,1, могут быть представлены точно. По сути, десятичный тип представляет это как 1/10 ^ 1, тогда как a double будет представлять это как 104857/2 ^ 20 (на самом деле это будет больше похоже на действительно большое число /2 ^ 1023).

A decimal может точно представлять любое значение базового значения 10 до 28/29 значащих цифр (например, 0,1). A double не может.

Ответ 5

Я понимаю, что большинство финансовых систем выражают валюту, используя целые числа, т.е. подсчитывая все в центах.

IEEE double precision фактически can представляет все целые числа точно в диапазоне от -2 ^ 53 до + 2 ^ 53. (Hacker Delight, стр. 262) Если вы используете только сложение, вычитание и умножение и сохраняете все до целых чисел в этом диапазоне, то вы не увидите потери точности. Однако я бы очень опасался деления или более сложных операций.

Ответ 6

Использование double, когда вы не знаете, что вы делаете, непригодно.

"double" может представлять собой сумму в триллион долларов с ошибкой 1/90 процента. Таким образом, вы получите очень точные результаты. Хотите рассчитать, сколько стоит положить мужчину на Марс и вернуть его обратно? двойной будет делать только отлично.

Но с деньгами часто бывают очень конкретные правила, говорящие, что определенный расчет должен дать определенный результат, а другой нет. Если вы подсчитаете сумму, которая очень очень близка к 98,35 долларам, тогда часто будет правило, определяющее, должен ли результат быть $98.14 или $98.13, и вы должны следовать этому правилу и получить требуемый результат.

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

Ответ 7

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

Ответ 8

На самом деле плавающая точка double отлично подходит для представления суммы денег, пока вы выбираете подходящую единицу.

См. http://www.idinews.com/moneyRep.html

Итак, фиксированная точка длинная. Либо потребляет 8 байтов, что предпочтительнее 16, потребляемых элементом десятичной.

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