Числовые типы с плавающей запятой (справочник по 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, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
В чем отличие float/double и decimal?
Здравствуйте, хотел попросить какие-то материалы, которые будут понятны новичку, насчёт ошибок округления и типа decimal, заранее спасибо!
- Вопрос задан более года назад
- 1702 просмотра
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 же напротив очень точный, но медленный.
Все о 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, который обусловит его поведение как двоичных данных.
Выбор между 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 может повлиять на производительность, поэтому его следует применять осознанно и в соответствии с потребностями задачи.