Какой тип данных лучше всего использовать для денег в C #?
using System.ComponentModel.DataAnnotations;
... [DataType(DataType.Currency)]
msdn.microsoft.com/en-us/library/…
Какой тип данных лучше всего использовать для денег в C #?
using System.ComponentModel.DataAnnotations;
... [DataType(DataType.Currency)]
msdn.microsoft.com/en-us/library/…
Ответы:
Как это описано в десятичном виде как:
Ключевое слово decimal указывает на 128-битный тип данных. По сравнению с типами с плавающей точкой, десятичный тип имеет большую точность и меньший диапазон, что делает его подходящим для финансовых и денежных расчетов.
Вы можете использовать десятичное число следующим образом:
decimal myMoney = 300.5m;
Тип десятичного значения представляет десятичные числа в диапазоне от положительных 79,228,162,514,264,337,593,543,950,335 до отрицательных 79,228,162,514,264,337,593,543,950,335. Тип десятичного значения подходит для финансовых расчетов, требующих большого количества значащих целых и дробных цифр и без ошибок округления. Тип Decimal не устраняет необходимость округления. Скорее, это минимизирует ошибки из-за округления.
Я хотел бы указать на этот превосходный ответ от zneak о том, почему не следует использовать double.
Используйте шаблон Money из Patterns of Enterprise Application Architecture ; укажите сумму в десятичном виде и валюту в виде перечисления.
Money
nuget есть мертвая ссылка на github для сайта проекта, так что ... нет документов?
Десятичный. Если вы выбираете double, вы оставляете себя открытым для ошибок округления
double
может привести к ошибкам округления, потому что с плавающей точкой невозможно точно представить все числа (например, 0,01 не имеет точного представления в плавающей точке). Decimal
с другой стороны, действительно представляет числа точно . (Компромисс Decimal
имеет меньший диапазон, чем с плавающей запятой). Плавающая точка может дать вам * непреднамеренные * ошибки округления (например 0.01+0.01 != 0.02
). Decimal
может дать вам ошибки округления, но только когда вы попросили об этом (например, Math.Round(0.01+0.02)
возвращает ноль)
double
и тщательно применяет масштабирование и округление, зависящее от предметной области, когда это уместно, оно может быть совершенно точным. Если кто-то неаккуратен в округлении, он decimal
может дать результаты, которые семантически неверны (например, если вы сложите несколько значений, которые должны быть округлены до ближайшей копейки, но на самом деле их сначала нет вокруг). Единственная хорошая вещь о decimal
том, что масштабирование встроено.
десятичная дробь имеет меньший диапазон, но большую точность - так что вы не потеряете все эти копейки со временем!
Полная информация здесь:
Согласитесь с шаблоном «Деньги»: работать с валютами слишком сложно, если вы используете десятичные дроби.
Если вы создаете класс Currency, вы можете поместить туда всю логику, связанную с деньгами, включая правильный метод ToString (), больший контроль над разбором значений и лучший контроль над делениями.
Кроме того, с классом Currency нет никакой возможности непреднамеренно смешать деньги с другими данными.
Другой вариант (особенно если вы катаетесь в своем собственном классе) - использовать int или int64 и обозначить четыре младшие цифры (или, возможно, даже 2) как «справа от десятичной точки». Так что «по краям» вам понадобится немного «* 10000» на входе и немного «/ 10000» на выходе. Это механизм хранения, используемый Microsoft SQL Server, см. Http://msdn.microsoft.com/en-au/library/ms179882.aspx.
Изюминка в том, что все ваше суммирование может быть выполнено с использованием (быстрой) целочисленной арифметики.
Большинство приложений, с которыми я работал, decimal
представляют деньги. Это основано на предположении, что приложение никогда не будет связано с более чем одной валютой.
Это предположение может основываться на другом предположении, что приложение никогда не будет использоваться в других странах с разными валютами. Я видел случаи, когда это оказалось ложным.
Теперь это предположение оспаривается по-новому: новые валюты, такие как биткойн, становятся все более распространенными, и они не характерны для какой-либо страны. Вполне возможно, что приложение, используемое только в одной стране, может по-прежнему поддерживать несколько валют.
Некоторые люди скажут, что создание или даже использование типа только для денег - это «золотое покрытие» или добавление дополнительной сложности сверх известных требований. Я категорически не согласен. Чем более вездесуща концепция в вашей области, тем важнее приложить разумные усилия, чтобы использовать правильную абстракцию заранее. Если вы хотите увидеть сложность, попробуйте работать в приложении, которое раньше использовало, decimal
и теперь Currency
рядом с каждым decimal
свойством есть дополнительное свойство.
Если вы используете неправильную абстракцию заранее, ее замена будет стоить больше работы. Это означает потенциальное внесение дефектов в существующий код, и, что самое приятное, эти дефекты, вероятно, будут связаны с денежными суммами, транзакциями с деньгами или просто с деньгами.
И это не так сложно использовать что-то кроме десятичной. Google "Nuget Money Type", и вы увидите, что многие разработчики создали такие абстракции (в том числе и я). Это легко. Это так же просто, как использовать DateTime
вместо сохранения даты в string
.
Создайте свой собственный класс. Это кажется странным, но тип .Net не подходит для разных валют.