Чем отличается decimal от double в C# и что выбрать для денег?
Запутался в типах для дробных чисел в C#. Есть double, есть decimal, есть float. В чём разница и что использовать, например, для хранения цены товара?
double price = 19.99;
decimal price2 = 19.99m;
Почему у второго в конце m?
2 ответа
Коротко: для денег всегда decimal, для научных/инженерных расчётов — double.
Разница в том, как хранятся числа:
double(иfloat) — двоичная плавающая точка. Быстрые, но не могут точно представить многие десятичные дроби. Классика:
double a = 0.1 + 0.2;
Console.WriteLine(a); // 0.30000000000000004
Console.WriteLine(a == 0.3); // False !!!
decimal— десятичная плавающая точка, 128 бит, до 28-29 значащих цифр. Точна для десятичных дробей, поэтому идеальна для финансов:
decimal a = 0.1m + 0.2m;
Console.WriteLine(a); // 0.3
Console.WriteLine(a == 0.3m); // True
Суффикс m (от money) обязателен у литералов decimal, иначе компилятор воспримет 19.99 как double и не даст присвоить. Аналогично f для float, d для double.
Плата за точность decimal — скорость (примерно в 10 раз медленнее double) и меньший диапазон. Поэтому в физике/графике берут double, а в бухгалтерии — decimal.
Запомнить просто по суффиксам литералов:
float f = 3.14f; // 32 бита, ~7 цифр
double d = 3.14; // 64 бита, ~15-16 цифр (по умолчанию для дробных)
decimal m = 3.14m; // 128 бит, ~28 цифр, точная для десятичных
Правило большого пальца: видишь рубли/доллары/проценты — пиши decimal. Всё остальное (координаты, скорость, тригонометрия) — double.