Числовые типы с плавающей запятой (справочник по C#)
Числовые типы с плавающей запятой представляют действительные числа. Все числовые типы с плавающей запятой являются типами значений. Они также представляют собой простые типы и могут быть инициализированы литералами. Все числовые типы с плавающей запятой поддерживают арифметические операторы, а также операторы сравнения и равенства.
Характеристики типов с плавающей запятой
C# поддерживает следующие предварительно определенные типы с плавающей запятой:
| Ключевое слово или тип C# | Приблизительный диапазон значений | Точность | Размер | Тип .NET |
|---|---|---|---|---|
| float | От ±1,5 x 10 −45 до ±3,4 x 10 38 | 6–9 цифр | 4 байта | System.Single |
| double | от ±5,0 × 10 −324 до ±1,7 × 10 308 | 15–17 цифр | 8 байт | System.Double |
| decimal | от ±1,0 x 10 -28 до ±7,9228 x 10 28 | 28-29 знаков | 16 байт | System.Decimal |
В приведенной выше таблице каждый тип ключевого слова C# из крайнего левого столбца является псевдонимом для соответствующего типа .NET. Они взаимозаменяемые. Например, следующие объявления объявляют переменные одного типа:
double a = 12.3; System.Double b = 12.3;
По умолчанию все типы с плавающей запятой имеют значение 0 . Все типы с плавающей запятой имеют константы MinValue и MaxValue с минимальным и максимальными итоговыми значениями этого типа. Типы float и double также предоставляют константы, обозначающие бесконечные и нечисловые значения. Например, тип double предоставляет следующие константы: Double.NaN, Double.NegativeInfinity и Double.PositiveInfinity.
Тип decimal подходит, если требуемая степень точности определяется числом цифр справа от десятичной запятой. Такие числа обычно используются в финансовых приложениях для денежных сумм (например, 1,00 долл. США), процентных ставок (например, 2,625 %) и т. д. Даже числа, точные только до одной десятичной цифры, точнее обрабатываются типом decimal : 0,1, например, можно в точности представить экземпляром decimal . При этом не существует экземпляра double или float , который точно представляет 0,1. Из-за этой разницы в числовых типах в арифметических вычислениях могут возникать непредвиденные ошибки округления при использовании double или float для десятичных данных. Вы можете использовать double вместо decimal , если оптимизация производительности важнее, чем обеспечение точности. Но любая разница в производительности останется незамеченной для всех приложений, кроме самых требовательных к вычислениям. Еще одна возможная причина, по которой следует избегать decimal , — это минимальные требования к хранилищу. Например, ML.NET использует float , так как разница между 4 байтами и 16 байтами суммируется для очень больших наборов данных. Для получения дополнительной информации см. System.Decimal.
В одном и том же выражении можно сочетать и целочисленные типы, и типы float и double . В этом случае целочисленные типы неявно преобразуются в один из типов с плавающей запятой. При необходимости тип float неявно преобразуется в double . Выражение вычисляется следующим образом.
- Если в выражении есть тип double , оно оценивается как double или bool в реляционных сравнениях или сравнениях на равенство.
- Если в выражении нет типа double , оно оценивается как float или bool в реляционных сравнениях или сравнениях на равенство.
Можно также смешивать целочисленные типы и тип decimal в выражении. В этом случае целочисленные типы неявно преобразуются в тип decimal , а выражение вычисляется как decimal или bool в реляционных сравнениях и сравнениях на равенство.
Тип decimal нельзя смешивать с типами float и double в выражении. В этом случае, если требуется выполнить арифметические операции или операции сравнения или равенства, необходимо явно преобразовать операнды из типа или в тип decimal , как показано в следующем примере:
double a = 1.0; decimal b = 2.1m; Console.WriteLine(a + (double)b); Console.WriteLine((decimal)a + b);
Можно использовать строки стандартных числовых форматов или строки пользовательских числовых форматов для форматирования значения с плавающей запятой.
Вещественные литералы
Тип реального литерала определяется его суффиксом следующим образом:
- Литерал без суффикса или с суффиксом d или D имеет тип double .
- Литерал с суффиксом f или F имеет тип float .
- Литерал с суффиксом m или M имеет тип decimal .
В приведенном ниже коде показан пример каждого из них.
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;
В предыдущем примере также показано использование _ в качестве разделителя цифр. Цифровой разделитель можно использовать со всеми видами числовых литералов.
Можно также использовать экспоненциальное представление, то есть указать экспоненту вещественного литерала, как показано в следующем примере:
double d = 0.42e2; Console.WriteLine(d); // output 42 float f = 134.45E-2f; Console.WriteLine(f); // output: 1.3445 decimal m = 1.5E6m; Console.WriteLine(m); // output: 1500000
Преобразования
Существует только одно неявное преобразование между числовыми типами с плавающей запятой: из float в double . Однако можно преобразовать любой тип с плавающей запятой в любой другой тип с плавающей запятой с помощьюявного приведения. Для получения дополнительной информации см. статью Встроенные числовые преобразования.
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
- Типы с плавающей запятой
- Тип decimal
- Вещественные литералы
См. также
- справочник по C#
- Типы значений
- Целочисленные типы
- Строки стандартных числовых форматов
- Числовые значения в .NET
- System.Numerics.Complex
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Выбор между decimal и double в C#: точность или производительность?


Выбор подходящего типа данных для работы с числами с плавающей точкой в C# может существенно повлиять как на точность вычислений, так и на производительность приложения. В этой статье мы рассмотрим различия между типами decimal и double , их предназначение, преимущества и недостатки, чтобы вы могли сделать обоснованный выбор в соответствии с потребностями вашего проекта.
Содержание показать
Основные различия между decimal и double
double и decimal в C# являются числовыми типами данных, используемыми для представления чисел с плавающей точкой. Основное различие между ними заключается в точности и диапазоне значений, которые они могут представлять.
double (или System.Double ) — это тип данных с плавающей точкой двойной точности, соответствующий стандарту IEEE 754. Этот тип данных предназначен для научных и инженерных расчётов, где необходим большой диапазон значений.
Пример кода с double :
double a = 0.1; double b = 0.2; double result = a + b; // Результат может быть не равен 0.3 из-за ошибок округления
decimal (или System.Decimal ) — это десятичный тип данных с высокой точностью, предназначенный для финансовых и монетарных расчётов, где важна высокая точность десятичных дробей.
Пример кода с decimal :
decimal a = 0.1m; // Суффикс "m" указывает на тип decimal decimal b = 0.2m; decimal result = a + b; // Результат будет точно 0.3
Точность и сценарии использования
Точность double
double имеет приблизительно 15-16 десятичных знаков точности. Это означает, что при выполнении математических операций с такими числами могут возникать ошибки округления. Это не всегда недостаток — для многих научных и инженерных задач такая точность более чем достаточна.
Читайте так же Проблемы создания сущности в LINQ to Entities и их решения
Точность decimal
В отличие от double , decimal имеет 28-29 значащих десятичных цифр, что делает его исключительно подходящим для работы с финансовыми данными, где важно сохранить каждую десятичную дробь.
Производительность
Производительность double
double обычно работает быстрее decimal , поскольку большинство современных процессоров оптимизированы для работы с плавающей точкой двойной точности. Для приложений, требующих высокой производительности и где допустимы небольшие погрешности в вычислениях, double часто является предпочтительным выбором.
Производительность decimal
decimal работает медленнее double , так как требует больше ресурсов для обеспечения высокой точности вычислений. Его следует использовать, когда точность превышает все остальные требования, например, при обработке финансовых транзакций.
Практические примеры и рекомендации
Примеры использования double
double earthMass = 5.972E24; // Масса Земли в килограммах double speedOfLight = 299792458; // Скорость света в метрах в секунду
double идеально подходит для физических расчётов, где не требуется абсолютная точность каждой десятичной дроби.
Примеры использования decimal
decimal accountBalance = 10000.50m; // Баланс банковского счёта decimal productPrice = 19.99m; // Цена товара
decimal необходим для точной работы с денежными суммами, где каждый цент имеет значение.
Заключение
Выбор между double и decimal в C# должен основываться на требованиях к точности и производительности вашего приложения. Для научных и инженерных расчётов double обычно является лучшим выбором из-за своей скорости и достаточной точности. Для финансовых приложений и везде, где требуется высокая точность десятичных чисел, следует использовать decimal . Важно помнить, что использование decimal может повлиять на производительность, поэтому его следует применять осознанно и в соответствии с потребностями задачи.
Чем отличается decimal от double?

Double это все числа с плавающей точкой, тоесть у decimal тоже есть плавающая точка, а значит decimal тоже double. Чтото тут не так.
Лучшие ответы ( 1 )
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Как преобразовать Double в Decimal?
Все очень просто Convert.ToDouble(value)
Аргумент 1 не удается преобразовать из double? в decimal
Не могу понять почему это происходит и как решить.Пишет аргумент 1 не удается преобразовать из.
Обрезать значение (усечь) decimal/double
Обрезать значение(усечь)decimal/double Привет всем, подскажите как правильно обрезать вывод.

Быстродействие double, decimal в x64
Работаю с финансовыми данными, максимальное количество знаков после запятой — 4. Получаю данные по.
![]()
17447 / 12836 / 3364
Регистрация: 17.09.2011
Сообщений: 21,119

Сообщение было отмечено как решение
Решение
1. double в памяти хранится в двоичном виде, а значит может отображать точно только те числа, которые являются степенью двойки. В противном случае возникают ошибки округления дробной части. decimal в памяти хранится в десятичном виде, потому с абсолютной точностью может отображать дробные части числа.
Decimal нужен там, где важна дробная часть. Например, при работе с финансами.
2. Double в памяти занимает 64 бита, а decimal — 128 бит.
3. У double больший диапазон чисел: против у decimal.
4. При этом, у double меньшая точность дробной части (15-16 цифр после запятой против 28-29 цифр у decimal).
5. У double есть особые значения: +0, -0, , , NaN. У decimal ничего подобного нет.
6. Double — нативный тип для процессора. Decimal — нет, потому операции с ним где-то в десять раз медленнее, чем с double.
Вроде бы ничего не забыл.
Сравнение производительности типов float, double и decimal в C#
Математический сопроцессор компьютера обычно дает лучшую производительность с определенным типом данных. Чтобы узнать, какая из них лучше всего работает в моей системе и узнать, насколько велика разница, я написал эту программу для сравнения производительности вычислений, которые используют float, double и decimal.
Введите несколько проб и нажмите кнопку «Перейти», чтобы выполнить следующий код.
// Сравнение характеристик. private void btnGo_Click(object sender, EventArgs e) < txtTimeFloat.Clear(); txtTimeDouble.Clear(); txtTimeDecimal.Clear(); Cursor = Cursors.WaitCursor; Refresh(); int num_trials = int.Parse(txtNumTrials.Text); Stopwatch watch = new Stopwatch(); float float1, float2, float3; double double1, double2, double3; decimal decimal1, decimal2, decimal3; watch.Start(); for (int i = 0; i < num_trials; i++) < float1 = 1.23f; float2 = 4.56f; float3 = float1 / float2; >watch.Stop(); txtTimeFloat.Text = watch.Elapsed.TotalSeconds.ToString() + " sec"; txtTimeFloat.Refresh(); watch.Reset(); watch.Start(); for (int i = 0; i < num_trials; i++) < double1 = 1.23d; double2 = 4.56d; double3 = double1 / double2; >watch.Stop(); txtTimeDouble.Text = watch.Elapsed.TotalSeconds.ToString() + " sec"; txtTimeDouble.Refresh(); // Масштабируем в 10 раз для десятичного. num_trials /= 10; watch.Reset(); watch.Start(); for (int i = 0; i < num_trials; i++) < decimal1 = 1.23m; decimal2 = 4.56m; decimal3 = decimal1 / decimal2; >watch.Stop(); txtTimeDecimal.Text = "~" + (watch.Elapsed.TotalSeconds * 10).ToString() + " sec"; Cursor = Cursors.Default; >
Код начинается с очистки текстовых полей результатов и получения количества желаемых результатов. Затем он запускает цикл, который выполняет простую математическую операцию в переменных float и отображает прошедшее время. Затем он повторяет эти шаги для типа данных double.
Далее код повторяет цикл для типа данных decimal. После запуска программы я обнаружил, что тип данных decimal был much медленнее, чем другие типы. Для запуска в течение разумного промежутка времени для десятичного типа данных программа делит количество испытаний на 10, а затем умножает прошедшее время на десять.
Если вы посмотрите внимательно на изображение, вы увидите, что для выполнения 100 миллионов вычислений программа использовала около 0,45 секунды для типа данных float, около 0.60 для double и, по оценкам, 22,04 секунды для типа данных decimal.
Мораль заключается в том, что если вы хотите производительность, используйте float. Если вам нужна большая точность, используйте double. Разница в производительности не такая уж большая.
Если вам нужна большая точность и вы готовы ждать намного дольше, используйте decimal. По крайней мере, на моем компьютере. Если вы запустите программу на своем компьютере и обнаружите, что двойной или десятичный результат дает более быстрый результат, чем float, отправьте комментарий ниже.