Я продолжаю наблюдать, как люди используют удвоение в С#. Я знаю, что я где-то читал, что удваивается, иногда теряют точность. Мой вопрос в том, когда следует использовать double и когда следует использовать десятичный тип? Какой тип подходит для расчета денег? (т.е. более 100 миллионов долларов)
Для денег всегда десятичный. Это почему оно было создано.
Если числа должны складываться корректно или сбалансированы, используйте десятичные числа. Это включает в себя любое финансовое хранение или расчеты, баллы или другие номера, которые люди могли бы сделать вручную.
Если точное значение чисел не важно, используйте double для скорости. Сюда входят вычисления графики, физики или других физических наук, где уже имеется "количество значимых цифр".
Мой вопрос в том, когда следует использовать double и когда следует использовать десятичную тип?
decimal
, когда вы работаете со значениями в диапазоне 10 ^ (+/- 28) и у вас есть ожидания относительно поведения на основе представлений базы 10 - в основном деньги.
double
, когда вам нужна относительная точность (т.е. потеря точности в конечных цифрах по большим значениям не является проблемой) через совершенно разные величины - double
охватывает более 10 ^ (+/- 300). Научные расчеты являются лучшим примером здесь.
какой тип подходит для денег вычисления?
десятичная, десятичная, десятичная
Не принимать замену.
Самый важный фактор заключается в том, что double
, реализуемый как двоичная дробь, не может точно представлять многие фракции decimal
(например, 0,1) вообще, и его общее количество цифр меньше, так как оно является 64-битным широм vs 128 бит для decimal
. Наконец, финансовые приложения часто должны следовать определенным режима округления (иногда это предусмотрено законом). decimal
поддерживает эти; double
не работает.
double
не следует использовать при представлении финансовых значений, но что именно вы имели в виду, когда писали, что double
не поддерживает конкретные режимы округления по сравнению с decimal
? Math.Round
, Math.Round
имеет перегрузки, которые принимают параметр MidpointRounding
как для double
и для decimal
?
System.Single/float - 7 цифры
System.Double/double - 15-16 цифр
System.Decimal/десятичный - 28-29 значительный цифры
То, как я был ужален, используя неправильный тип (несколько лет назад), имеет большие суммы:
У вас заканчивается 1 миллион для поплавка.
15-значное денежное значение:
9 триллионов с двойным. Но с разделением и сравнением это сложнее (я определенно не эксперт в области с плавающей запятой и иррациональными числами - см. Пункт Marc). Смешивание десятичных знаков и удвоений вызывает проблемы:
Математическая или сравнительная операция который использует число с плавающей запятой может не дать тот же результат, если десятичное число используется, поскольку число с плавающей запятой может не совпадать точно приблизить десятичную число.
Когда следует использовать double вместо десятичного? имеет похожие и более подробные ответы.
Использование double
вместо decimal
для денежных приложений - это микро-оптимизация - это самый простой способ посмотреть на нее.
520,532.52
имеет 8 значимых чисел и 1 1,323,523.12
имеет 9 mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm
Десятичное значение для точных значений. Двойной для приблизительных значений.
USD: $12,345.67 USD (Decimal)
CAD: $13,617.27 (Decimal)
Exchange Rate: 1.102932 (Double)
За деньги: decimal
. Это стоит немного больше памяти, но не имеет проблем округления, например, double
.
1m/3m + 1m/3m == 2m/3m
. Основное различие заключается в том, что для значащего и большего числа битов самое важное: нет потери точности при работе с числами с 5 при простом делении делителя. Например. 1m/5m + 1m/5m
будет точно равен 2m/5m
.
Определенно использовать целые типы для ваших денежных расчетов. Это не может быть подчеркнуто достаточно, так как на первый взгляд может показаться, что тип с плавающей точкой является адекватным.
Вот пример кода python:
>>> amount = float(100.00) # one hundred dollars
>>> print amount
100.0
>>> new_amount = amount + 1
>>> print new_amount
101.0
>>> print new_amount - amount
>>> 1.0
выглядит довольно нормально.
Теперь попробуйте еще раз с 10 ^ 20 долларами Зимбабве
>>> amount = float(1e20)
>>> print amount
1e+20
>>> new_amount = amount + 1
>>> print new_amount
1e+20
>>> print new_amount-amount
0.0
Как вы можете видеть, доллар исчез.
Если вы используете целочисленный тип, он отлично работает:
>>> amount = int(1e20)
>>> print amount
100000000000000000000
>>> new_amount = amount + 1
>>> print new_amount
100000000000000000001
>>> print new_amount - amount
1
Я думаю, что основное отличие от ширины бита состоит в том, что десятичное число имеет базу экспонентов 10 и double имеет 2
http://software-product-development.blogspot.com/2008/07/net-double-vs-decimal.html