десятичный против двойного! - Какой я должен использовать и когда? [Дубликат]

757

Я продолжаю наблюдать, как люди используют удвоение в С#. Я знаю, что я где-то читал, что удваивается, иногда теряют точность. Мой вопрос в том, когда следует использовать double и когда следует использовать десятичный тип? Какой тип подходит для расчета денег? (т.е. более 100 миллионов долларов)

  • 4
    Вы хотите доли центов? (как на автозаправках)
  • 0
    stackoverflow.com/questions/803225/...
Показать ещё 2 комментария
Теги:
decimal
double
currency
precision

7 ответов

952
Лучший ответ

Для денег всегда десятичный. Это почему оно было создано.

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

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

  • 36
    Дело не в том, что double неточен - он имеет относительную точность и может представлять очень большие или малые величины, с которыми десятичная дробь не может справиться вообще.
  • 68
    Вот почему вы используете Десятичное для денег: точность Double составляет всего 16 десятичных цифр, и после всего лишь нескольких арифметических операций ошибки будут быстро накапливаться достаточно большими, чтобы переходить в 15, 14, 13 и т. Д. Цифры. Для округления до «центов» требуется, по крайней мере, одна цифра полной точности после цифры в центах, но на самом деле вы должны зарезервировать 4 или 5 для защиты от кумулятивных арифметических ошибок, которые вы НЕ МОЖЕТЕ испортить в сотых столбцах, которые вы используете для округления центов. Таким образом, вы получите 16 (всего) - 2 (центов) - (4 или 5 ошибок заполнения) = oh $ Хит только 7 (или менее) надежных целых цифр за ваши деньги!
Показать ещё 13 комментариев
150

Мой вопрос в том, когда следует использовать double и когда следует использовать десятичную тип?

decimal, когда вы работаете со значениями в диапазоне 10 ^ (+/- 28) и у вас есть ожидания относительно поведения на основе представлений базы 10 - в основном деньги.

double, когда вам нужна относительная точность (т.е. потеря точности в конечных цифрах по большим значениям не является проблемой) через совершенно разные величины - double охватывает более 10 ^ (+/- 300). Научные расчеты являются лучшим примером здесь.

какой тип подходит для денег вычисления?

десятичная, десятичная, десятичная

Не принимать замену.

Самый важный фактор заключается в том, что double, реализуемый как двоичная дробь, не может точно представлять многие фракции decimal (например, 0,1) вообще, и его общее количество цифр меньше, так как оно является 64-битным широм vs 128 бит для decimal. Наконец, финансовые приложения часто должны следовать определенным режима округления (иногда это предусмотрено законом). decimal поддерживает эти; double не работает.

  • 2
    Нет сомнений в том, что double не следует использовать при представлении финансовых значений, но что именно вы имели в виду, когда писали, что double не поддерживает конкретные режимы округления по сравнению с decimal ? Math.Round , Math.Round имеет перегрузки, которые принимают параметр MidpointRounding как для double и для decimal ?
  • 2
    @Groo: Наверное, я посмотрел на .Net 1.1 API, метод был добавлен в 2.0 - но он все еще бессмыслен из-за проблем с двоичными дробями. В текущем документе API есть пример, иллюстрирующий эту проблему.
Показать ещё 3 комментария
35

System.Single/float - 7 цифры
System.Double/double - 15-16 цифр
System.Decimal/десятичный - 28-29 значительный цифры

То, как я был ужален, используя неправильный тип (несколько лет назад), имеет большие суммы:

  • £ 520,532,52 - 8 цифр
  • £ 1 323 523,12 - 9 цифр

У вас заканчивается 1 миллион для поплавка.

15-значное денежное значение:

  • £ 1,234,567,890,123.45

9 триллионов с двойным. Но с разделением и сравнением это сложнее (я определенно не эксперт в области с плавающей запятой и иррациональными числами - см. Пункт Marc). Смешивание десятичных знаков и удвоений вызывает проблемы:

Математическая или сравнительная операция который использует число с плавающей запятой может не дать тот же результат, если десятичное число используется, поскольку число с плавающей запятой может не совпадать точно приблизить десятичную число.

Когда следует использовать double вместо десятичного? имеет похожие и более подробные ответы.

Использование double вместо decimal для денежных приложений - это микро-оптимизация - это самый простой способ посмотреть на нее.

31

Десятичное значение для точных значений. Двойной для приблизительных значений.

USD: $12,345.67 USD (Decimal)
CAD: $13,617.27 (Decimal)
Exchange Rate: 1.102932 (Double)
  • 8
    Десятичный не для точных значений. Десятичное число обеспечивает 28-29 десятичных знаков точности в соответствии с документацией. Десятичное число не выполняет аналитическую арифметику и поэтому не является «точным». Десятичная дробь отлично подходит для денег, потому что даже при значениях в триллионах долларов она все равно оставляет 10 цифр изоляции от кумулятивной арифметической ошибки, и в то же время она может точно округлять до центов.
  • 5
    Почему обменный курс двойной, а не десятичный? Разве это не просто цена 1 доллара в канадских долларах?
Показать ещё 9 комментариев
23

За деньги: decimal. Это стоит немного больше памяти, но не имеет проблем округления, например, double.

  • 7
    у него есть все проблемы с округлением: попробуйте 1m/3m + 1m/3m == 2m/3m . Основное различие заключается в том, что для значащего и большего числа битов самое важное: нет потери точности при работе с числами с 5 при простом делении делителя. Например. 1m/5m + 1m/5m будет точно равен 2m/5m .
6

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

Вот пример кода 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
  • 5
    Вам даже не нужны очень большие / маленькие значения, чтобы найти различия между приближениями типа double2 и фактическими значениями base 10, многие небольшие значения не могут быть точно сохранены. Вычислите «1 - 0,1 - 0,9» (убедитесь, что компилятор не оптимизирует уравнение) и сравните его с нулем. Вы обнаружите, что с двойным результатом будет что-то вроде 2e-17 вместо 0 (убедитесь, что вы выполняете сравнение, так как многие функции print / ToString округляют до определенного числа десятичных разрядов, чтобы удалить ошибки такого типа).
  • 1
    целое число ?! и что происходит, когда у вас есть 1,5 доллара?
Показать ещё 4 комментария
4

Я думаю, что основное отличие от ширины бита состоит в том, что десятичное число имеет базу экспонентов 10 и double имеет 2

http://software-product-development.blogspot.com/2008/07/net-double-vs-decimal.html

Ещё вопросы

Сообщество Overcoder
Наверх
Меню