В чем разница между decimal и double?

В разных языках программирования есть различные типы представления чисел с плавающей точкой.
Всем знакомые типы float, double, decimal, number, numeric.
Между первым и вторым разница только в одном — это размер памяти, которую они занимают. И следовательно кол-во значений, которые можно описать этими типами.
В отличие от первых двух, тип decimal не только занимает больше памяти, но и кардинально отличается от них.
Часто говорят, что тип decimal нужно использовать для вычислений, где необходима точность. Можно порассуждать и подумать, что она вообще-то нужна везде.
Так же в C# если сложить переменные типа double или float со значениями 0.1 и 0.2 и сравнить с 0.3, то мы удивимся, когда узнаем, что 0.1+0.2 ≠ 0.3
Хороший вопрос — И тогда зачем нам вообще нужны типы вида float и double.
Обо всем по порядку:
Тип double, несмотря на меньший размер занимаемой памяти может хранить большее кол-во значений, чем decimal. А все за счёт внутреннего устройства.
Любое число в компьютере хранится в двоичном виде, из нулей и единиц. Преобразование целых чисел простая задача. Однако представление вещественного числа и есть ключ к разгадке.
Тип double представляется в виде последовательности нулей и единиц с плавающей точкой. Если коротко, то дробная часть будет храниться в битах, которые представлены в виде отношения 1 на степень двойки, 1/2, 1/4, 1/8, 1/16 и тд.
Разные комбинации сумм и дают разные результаты.
Тип decimal в отличие от float и double хранится как целое число и смещение десятичной запятой. Например число 12.75 хранится как 1275 и значение смещения 2. И такие значения дают большую точность, чем сумма дробей.
Такая разница и приводит к различным выборам в пользу одного или другого решения.
В выборе между ними можно руководствоваться следующими пунктами:
Если нужна абсолютная точность: финансовые расчеты, координаты и тд, то выбираем decimal.
Если точность не важна: вычисляем рост, вес, различные физические значения, то выбираем double.
Если необходимо экономить память и можно пренебречь точностью — выбираем double.
Было интересно? Устанавливай связь, делись с коллегами. Впереди больше интересного
В чем отличие float/double и decimal?
Здравствуйте, хотел попросить какие-то материалы, которые будут понятны новичку, насчёт ошибок округления и типа decimal, заранее спасибо!
- Вопрос задан 28 дек. 2022
- 1318 просмотров
1 комментарий
Простой 1 комментарий
В MSDN смотрели?
https://learn.microsoft.com/ru-ru/dotnet/csharp/la.
Решения вопроса 1

Василий Банников @vabka Куратор тега C#
Токсичный шарпист
float и double — это числа с плавающей точкой по стандарту IEEE754. Операции с ними происходят достаточно быстро, тк они реализованы в процессоре на аппаратном уровне.
Но они достаточно не точные в плане выражения десятичных дробей. (То самое 0.1+0.2 != 0.3).
Настоящие деньги на них считать не следует.
decimal же напротив очень точный, но медленный.
Типы данных для C#: минимум, который необходимо знать

C# является строго типизированным языком. В языках такого типа каждая переменная и константа имеет свой тип, результатом вычисления которого является некое значение. В стандартной библиотеке классов .NET определены встроенные числовые типы и комплексные типы. Об особенностях применения этих разных типов данных мы и поговорим в этой обзорной статье.
Професійний курс від laba: Проджект-менеджмент в ІТ.
Ефективне управління проектами.
Содержание статьи:
Введение
Типы данных используются для управления переменными. Каждый из типов данных обрабатывается в соответствии с определенными правилами. Поскольку C# — язык со строгой типизацией, то абсолютно все выполняемые операции проверяются на соответствие типов (во избежание ошибок производится их предварительный контроль). Если какая-либо операция с типами недопустима, итоговая программа не будет скомпилирована. По сути, разработка программного обеспечения на C# представляет собой создание и организацию взаимодействия между различными типами данных.
В языке C# типы данных имеют две категории:
Практичний курс від skvot: Артменеджер.
Управляйте творчим процесом.
- Типы значений — это тип данных, содержащий значения данных в собственном пространстве памяти. Хранятся в стеке, а потому их можно быстро создавать и удалять.
- Ссылочные типы — хранят ссылку на значения и указывают на другую ячейку памяти, в которой хранятся данные. Хранятся в управляемой куче.
Подразделение типов значения
- Целочисленные типы ( byte , sbyte , short , ushort , int , uint , long , ulong );
- Типы с плавающей запятой ( float , double );
Освітній курс від mate.academy: UI/UX Design.
Творчий розвиток навичок дизайну.
Подразделение ссылочных типов
- Object ;
- String ;
- Class ;
- Interface ;
Использование суффиксов float, decimal, double
У некоторых числовых типов имеются суффиксы, позволяющие записывать значение типа в переменную.
Числовые типы с плавающей запятой — это действительные числа. Они принадлежат к категории Типы значения. Это простые типы, которые могут быть инициализированы литералами. Они поддерживают операторы сравнения, равенства и арифметические операторы.
| Тип C# | Диапазон | Точность/Знаков после запятой | Размер/байт | Системный тип |
| float | ±1,5 x 10-45…±3,4 x 1038 | 6-9 | 4 | System.Single |
| double | ±5,0 × 10-324…±1,7 × 10308 | 15-17 | 8 | System.Double |
| decimal | ±1,0 x 10-28…±7,9228 x 1028 | 28-29 | 16 | System.Decimal |
Ключевые слова из колонки Тип C# взаимозаменяемы с системными типами.
double a = 12.3; System.Double b = 12.3;
Все типы с плавающей запятой имеют свои константы MaxValue и MinValue . Типы float и double в дополнение имеют константы, которые обозначают нечисловые и бесконечные значения.
Цифровий курс від robotdreams: DevOps Engineer.
підходи для створення сучасних і масштабованих застосунків.
С# decimal format подходит тогда, когда необходима точность, определяемая числом цифр справа от запятой. Числа с точностью до одной десятичной цифры наиболее точно обрабатывают тип decimal . В double или float в десятичных данных могут возникать ошибки.
С# decimal VS double
В случаях, когда производительность важнее точности, тип decimal ( c# format decimal ) можно заменить типом double .
Литералы
Тип определяется суффиксом:
-
double имеет суффиксы D или d ;
double d = 3D; d = 4d; d = 3.934_001; float f = 3_000.5F; f = 5.4f; decimal myMoney = 3_000.5m; myMoney = 400.75M;
Decimal и float
Decimal и float используются для хранения числовых значений:
- Float является 32-битным типом данных с приблизительным числом. Не все значения в диапазоне типов данных могут быть точными, значения округляются;
- Decimal является 128-битным типом данных с фиксированной точностью. Все значения в диапазоне типов данных представлены с точностью и масштабом, значения не округляются;
- Decimal чаще всего используется в финансовых приложениях, требующих высокой точности без ошибок округления, а float используется для хранения чисел и повышения производительности.
C# convert to decimal
Класс convert создан для того, чтобы преобразовывать широкий спектр типов. С его помощью можно преобразовывать в десятичное число больше типов. Метод Convert.ToDecimal используется для преобразования строкового представления числа в эквивалентное десятичное число с информацией о форматировании.
// C# program to demonstrate the // Convert.ToDecimal() Method using System; using System.Globalization; class GFG < // Main Method public static void Main() < try < // creating object of CultureInfo CultureInfo cultures = new CultureInfo("en-US"); // declaring and initializing String array string[] values = ; // calling get() Method Console.WriteLine("Converted decimal value "+ "of specified strings: "); for (int j = 0; j < values.Length; j++) < get(values[j], cultures); >> catch (FormatException e) < Console.WriteLine("\n"); Console.Write("Exception Thrown: "); Console.Write("", e.GetType(), e.Message); > catch (OverflowException e) < Console.WriteLine("\n"); Console.Write("Exception Thrown: "); Console.Write("", e.GetType(), e.Message); > > // Defining get() method public static void get(string s, CultureInfo cultures) < // converting string to specified char decimal val = Convert.ToDecimal(s, cultures); // display the converted char value Console.Write(" , ", val); > >
Вывод: преобразование в десятичное значение указанных строк:
123456789, 12345.6789, 123456789.0123.
C# decimal to int
Метод Decimal.ToInt32() создан для преобразования decimal значения в эквивалентное 32-разрядное целое число со знаком.
/ C# program to demonstrate the // Decimal.ToInt32(Decimal) Method using System; class GFG < // Main Method public static void Main() < try < // Taking decimal variables Decimal dec1 = 2147483647M; Decimal dec2 = 21458565.2996m; // using Decimal.ToInt32(Decimal) Method // Here int means Int32 int val1 = Decimal.ToInt32(dec1); // using Decimal.ToInt32(Decimal) Method // Here int means Int32 int val2 = Decimal.ToInt32(dec2); // Printing the Int32 value Console.WriteLine("The Int32 value " + "is : ", val1); // Printing the Int32 value Console.WriteLine("The Int32 value " + "is : ", val2); > catch (OverflowException e) < Console.Write("Exception Thrown: "); Console.Write("", e.GetType(), e.Message); > > >
Вывод: Int32: 2147483647 и Int32: 21458565 .
C# decimal round
Decimal.Round() или С# round decimal представляет собой метод округления к ближайшему целому числу или указанному количеству десятичных знаков.
Существует 4 способа округления:
1 Decimal round С# , то есть десятичный метод — Round(Decimal) Method — округление десятичного значения до ближайшего целого числа;
// C# program to demonstrate the // Decimal.Round(Decimal) Method using System; class GFG < // Main Method public static void Main() < try < // Declaring and initializing value decimal value = 184467440737095.51615M; // getting rounded decimal // using Round() method decimal round = Decimal.Round(value); // Display the value Console.WriteLine("Rounded value is ", round); > catch (OverflowException e) < Console.WriteLine("Value must not be out of bound"); Console.Write("Exception Thrown: "); Console.Write("", e.GetType(), e.Message); > > >
Вывод: округленное значение 184467440737096.
2 Round(Decimal, Int32) Method — округление значения Decimal до указанного количества десятичных знаков;
// C# program to demonstrate the // Decimal.Round(Decimal) Method using System; class GFG < // Main Method public static void Main() < try < // Declaring and initializing value decimal value = 7922816251426433759354.39503305M; // getting rounded decimal // using Round() method decimal round = Decimal.Round(value, 4); // Display the value Console.WriteLine("Rounded value is ", round); > catch (ArgumentOutOfRangeException e) < Console.WriteLine("decimal place is not within bound"); Console.Write("Exception Thrown: "); Console.Write("", e.GetType(), e.Message); > > >
Вывод: округленное значение 7922816251426433759354,3950 .
3 Round(Decimal, Int32, MidpointRounding) Method ;
4 Round(Decimal, MidpointRounding) Method .
Таблица некоторых типов C# и их сочетание с системными типами
Название встроенного типа (столбец Ключевое слово) — и есть сокращенное обозначение системного типа (столбец Системный тип).
| Ключевое слово | Системный тип | Описание и диапазон значений | Размер |
| byte | System.Byte | Структура. Целое число 0…255. | 1 байт |
| sbyte | System.SByte | Структура. Целое число -128…127. | 1 байт |
| short | System.Int16 | Структура. Целое число -32768…32767. | 2 байта |
| ushort | System.UInt16 | Структура. Целое число 0…65535. | 2 байта |
| int | System.Int32 | Структура. Целое число -2147483648…2147483647. | 4 байта |
| uint | System.UInt32 | Структура. Целое число 0…4294967295. | 4 байта |
| long | System.Int64 | Структура. Целое число –9 223 372 036 854 775 808…9 223 372 036 854 775 807. | 8 байт |
| ulong | System.UInt64 | Структура. Целое число 0…18 446 744 073 709 551 615. | 8 байт |
| float | System.Single | Структура. Число с плавающей точкой -3.4*1038…3.4*1038 | 4 байта |
| double | System.Double | Структура. Число с плавающей точкой ±5.0*10-324…±1.7*10308 | 8 байт |
| decimal format c# | System.Decimal | Структура. Десятичное дробное число. Без десятичной запятой ±1.0*10-28…±7.9228*1028, хранит до 28 знаков после запятой. | 16 байт |
| bool | System.Boolean | Структура. Хранит логические литералы true или false. | 1 байт |
| char | System.Char | Структура. Хранит одиночный символ в Unicode. | 2 байта |
| object | System.Object | Класс. Хранит значение любого типа данных. | — |
| string | System.String | Класс. Хранит набор символов Unicode. | — |
Неявная типизация
Чтобы указать призвольный тип переменных, можно использовать неявную типизацию. Для этого используется ключевое слово var .
var hello = "Привет, мир!"; var c = 20; Console.WriteLine(c.GetType().ToString()); Console.WriteLine(hello.GetType().ToString());
Var используется вместо названия типа данных. Присвоенное значение позволяет компилятору выводить тип данных. В примере Console.WriteLine(c.GetType().ToString()) ; определяет тип переменной с . Целочисленные значения по умолчанию рассматриваются как int , поэтому переменная с имеет тип System.Int32 .
Но такие переменные имеют свои ограничения:
1 Нельзя определить неявную переменную и сразу ее инициализировать.
// верно int a; a = 20; // неверно var c; c = 20;
2 Неявная переменная не может иметь значение null , в этом случае компилятор не определит автоматически тип данных.
// неверно var c=null;
Double или format decimal C#?
Для больших дробных чисел проще всего использовать тип double . Decimal имеет большую разрядность в сравнении с double , но double хранит большее значение.
После запятой decimal может иметь до 28 цифр, тогда как double — до 16. Тем не менее double широко используется в математических вычислениях, а decimal — в финансовых.
Таблица различий между double и decimal
| Максимальное значение | Минимальное значение | Цифр после запятой | Размер | Количество операций | |
| double | ~10308 | ~10-323 | 16 | 8 байт | миллиарды в секунду |
| decimal | ~1028 | 10-28 | 28 | 16 байт | сотни миллионов в секунду |
Итог
Типы данных могут быть простыми и сложными. Сложные типы чаще всего данные структурируют, а у простых значения данных неделимы. Любой язык программирования имеет систему встроенных типов данных, на их основе можно создавать свои производные.
В C# типы данных подразделяются на две большие группы:
- типы значений (входит большинство встроенных типов в т.ч. пользовательские) — для их создания применяется ключевое слово struct ;
- ссылочные типы — для их создания применяется ключевое слово class .
Закрепить материал по типам C#-данных можно на основе этого замечательного видео, где дополняется все сказаное нами:
Все о MySQL. Типы FLOAT, DOUBLE, DECIMAL
Для работы с вещественными числами в MySQL предусмотрено три типа данных — это типы FLOAT, DOUBLE, DECIMAL. Числовой тип FLOAT предназначен для представления вещественных чисел одинарной точности, в то время как типы данных DOUBLE и DECIMAL служат для представления вещественных чисел двойной точности.
Как и целые типы, эти типы принимают дополнительные аргументы: спецификацию ширины отображения и спецификацию десятичной части числа. Например, объявление FLOAT(5,2) задает длину отображаемых значений, равной не более 5 цифрам с двумя цифрами после десятичной точки. Рассмотрим примеры, которые это демонстрируют.
+————+
4 rows л_п set (0.00 sec)
Значения, содержащие цифры после десятичной точки в количестве больше допустимого, автоматически округляются до ближайшего значения и только потом добавляются. Это демонстрирует следующий пример.
Тип данных DECIMAL используется в вычислениях, требующих предельной точности, т.к. этот тип позволяет задавать в качестве дополнительных аргументов точность и масштаб. Здесь точность относится к количеству значащих цифр, которые могут храниться в значении, а масштаб — количество цифр после десятичной точки. Так, например, объявление DECIMAL (5,2) задает хранение значений, которые содержат не более 5 цифр при 2 цифрах после десятичной точки. Рассмотрим следующий пример, в котором это продемонстрировано.
На заметку
Для более точного сохранения значений, MySQL хранит типы данных DECIMAL в символических строках.
Пропуск спецификации точности и масштаба для типа DECIMAL приводит к присвоению по умолчанию полям, объявленным таким образом, значения аргумента точности, равного 10, и масштаба, равного 0.
Листинг 5.9.
mysql> CREATE TABLE data (f_decimal DECIMAL);
Query OK, 0 rows affected (0.00 sec)
Модификаторы UNSIGNED и ZEROFILL можно использовать и с типами данных FLOAT, DOUBLE, DECIMAL, при этом они действуют так же, как и в случае целых типов данных.
Строковые типы данных
MySQL имеет восемь основных строковых типов, которые можно использовать для хранения строковых данных, начиная с простейших строк, содержащих один символ, и заканчивая большими текстовыми или двоичными блоками данных. Перечень этих типов приводится в табл. 5.2.
Типы CHAR и VARCHAR
Простейшим из всех перечисленных в табл. 5.2 типов является тип CHAR, который используется со строками фиксированной длины и объявляется со спецификацией размера, заключающейся в скобки. Размер может лежать в диапазоне от 0 до 255 и определять длину хранящегося значения — например, объявление CHAR(10) задает максимальную длину хранящейся строки, равной 10 символам. Значения меньше заданной длины будут дополняться справа нулями, значения больше указанной длины будут автоматически усечены. Обе эти ситуации продемонстрированы в следующем примере.
Тип CHAR принимает необязательный модификатор BINARY, который приводит к обработке данного поля при операциях сравнения как двоичного (а не традиционного текстового). Следующий пример это наглядно демонстрирует.
Таким образом, мы видим, что MySQL при использовании типа CHAR позволяет производить поиск без учета регистра, между строками ‘hugo’ и ‘HUGO’. А теперь посмотрим, что происходит, если добавить к этому же объявлению модификатор BINARY.
Так как теперь для объявления поля используется двоичный тип, MySQL осуществляет двоичное сравнение, что совершенно очевидно приводит к сбою из-за несоответствия регистра. Одним из вариантов типа CHAR является тип VARCHAR, который используется для хранения строк переменной длины, он также должен сопровождаться спецификацией длины в диапазоне от 0 до 255. Разница между типами CHAR и VARCHAR заключается в том, как MySQL обрабатывает эту спецификацию. Тип CHAR считает это точной длиной значения, дополняя все значения, имеющие длину меньше заданной пробелами, в то время как тип VARCHAR рассматривает это как максимальный размер значений и использует только число байтов, действительно необходимых для хранения строки (плюс один байт, необходимый для хранения длины). Таким образом, короткие значения при сохранении в поле, которое сохраняется, как тип VARCHAR не дополняется пробелами. (А все более длинные значения также усекаются.)
Так как поля могут динамически расширяться и сужаться в зависимости от содержимого, этот тип лучше всего использовать тогда, когда вы не совсем уверены, сколько символов должно хранить данное поле. Тип VARCHAR использует только минимальное количество необходимых байтов, что может привести к повышению эффективности хранения и, возможно, к существенному улучшению рабочих характеристик разрабатываемой базы данных.
Как и тип CHAR, тип VARCHAR может сопровождаться необязательным модификатором BINARY, который обусловит его поведение как двоичных данных.