В чем разница между decimal
, float
и double
в .NET?
Когда кто-то воспользуется одним из них?
18 ответов
float
и double
- это двоичные типы с плавающей запятой.. Другими словами, они представляют собой такие числа:
10001.10010110011
Двоичное число и расположение двоичной точки закодированы внутри значения.
decimal
- это плавающий десятичный тип точки. Другими словами, они представляют собой такие числа:
12345.65789
Опять же, число и расположение десятичной точки закодированы внутри значения - это то, что делает decimal
по-прежнему типом с плавающей запятой, а не с фиксированной запятой.
Важно отметить, что люди привыкли представлять нецелые числа в десятичной форме и ожидать точных результатов в десятичных представлениях; не все десятичные числа точно могут быть представлены в двоичном формате с плавающей запятой - например, 0,1 - поэтому, если вы используете двоичное значение с плавающей запятой, вы фактически получите приближение к 0,1. Вы по-прежнему будете получать приближения при использовании десятичной запятой с плавающей запятой - например, результат деления 1 на 3 не может быть точно представлен.
Что использовать, когда:
Для значений, которые являются "естественно точными десятичными знаками", хорошо использовать
decimal
. Обычно это подходит для любых концепций, изобретенных людьми: наиболее очевидным примером являются финансовые ценности, но есть и другие. Рассмотрим, например, оценку, которую получают ныряльщики или фигуристы.Для значений, которые представляют собой скорее артефакты природы, которые в любом случае нельзя измерить точно , более подходят
float
/double
. Например, в этой форме обычно представлены научные данные. Здесь исходные значения не будут «десятичными точными» для начала, поэтому для ожидаемых результатов не важно поддерживать «десятичную точность». Типы с плавающей двоичной точкой работают намного быстрее, чем с десятичными.
Главное отличие - точность.
Float - 7 цифр (32 бит)
Double -15-16 цифр (64 бит)
Decimal -28-29 значащих цифр (128 бит)
Десятичные дроби имеют гораздо более высокую точность и обычно используются в финансовых приложениях, требующих высокой степени точности. Десятичные дроби намного медленнее (до 20 раз в некоторых тестах), чем double / float.
Десятичные дроби и числа с плавающей запятой / двойные числа нельзя сравнивать без приведения типов, тогда как числа с плавающей запятой и двойные числа могут. Десятичные дроби также позволяют кодировать или нули в конце.
float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
Результат:
float: 0.3333333
double: 0.333333333333333
decimal: 0.3333333333333333333333333333
+---------+----------------+---------+----------+---------------------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32,768 to 32,767 |
| int | System.Int32 | Yes | 4 | -2,147,483,648 to 2,147,483,647 |
| long | System.Int64 | Yes | 8 | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65,535 |
| uint | System.UInt32 | No | 4 | 0 to 4,294,967,295 |
| ulong | System.Uint64 | No | 8 | 0 to 18,446,744,073,709,551,615 |
| float | System.Single | Yes | 4 | Approximately ±1.5e-45 to ±3.4e38 |
| | | | | with ~6-9 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0e-324 to ±1.7e308 |
| | | | | with ~15-17 significant figures |
| decimal | System.Decimal | Yes | 16 | Approximately ±1.0e-28 to ±7.9e28 |
| | | | | with 28-29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------------------+
Дополнительную информацию см. здесь.
Структура Decimal строго предназначена для финансовых расчетов, требующих точности, которые относительно нетерпимы к округлению. Однако десятичные дроби не подходят для научных приложений по нескольким причинам:
- Некоторая потеря точности допустима во многих научных расчетах из-за практических ограничений измеряемой физической проблемы или артефакта. В финансах потеря точности недопустима.
- Decimal намного (намного) медленнее, чем float и double для большинства операций, в первую очередь потому, что операции с плавающей запятой выполняются в двоичном формате, тогда как Decimal выполняется в базе 10 (т.е. с плавающей точкой и двойными числами обрабатываются аппаратным обеспечением FPU, таким как MMX / SSE , а десятичные дроби рассчитываются программно).
- Decimal имеет недопустимо меньший диапазон значений, чем double, несмотря на то, что он поддерживает большее количество цифр точности. Следовательно, Decimal нельзя использовать для представления многих научных значений.
Я не буду повторять тонны хорошей (и некоторой плохой) информации, на которую уже были даны ответы в других ответах и комментариях, но я отвечу на ваш последующий вопрос советом:
Когда кто-нибудь будет использовать один из них?
Используйте десятичные числа для подсчитанных значений
Используйте float / double для измеренных значений
Некоторые примеры:
деньги (мы деньги считаем или измеряем?)
расстояние (мы считаем расстояние или измеряем расстояние? *)
баллы (мы подсчитываем баллы или измеряем баллы?)
Мы всегда считаем деньги и никогда не должны их измерять. Обычно мы измеряем расстояние. Мы часто считаем баллы.
* В некоторых случаях то, что я бы назвал номинальным расстоянием , мы действительно можем захотеть «подсчитать» расстояние. Например, возможно, мы имеем дело со знаками страны, которые показывают расстояния до городов, и мы знаем, что на этих расстояниях никогда не бывает более одной десятичной цифры (xxx.x км).
float
7 знаков точности
double
имеет около 15 знаков точности
decimal
имеет около 28 знаков точности
Если вам нужна более высокая точность, используйте double вместо float. В современных процессорах оба типа данных имеют почти одинаковую производительность. Единственное преимущество использования поплавков - они занимают меньше места. Практически имеет значение, только если у вас их много.
Я нашел это интересным. Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой а>
Никто не упомянул, что
В настройках по умолчанию Floats (System.Single) и double (System.Double) никогда не будут использовать проверку переполнения, в то время как Decimal (System.Decimal) всегда будет использовать проверку переполнения.
Я имею в виду
decimal myNumber = decimal.MaxValue;
myNumber += 1;
Выбрасывает OverflowException .
Но это не так:
float myNumber = float.MaxValue;
myNumber += 1;
&
double myNumber = double.MaxValue;
myNumber += 1;
Как уже упоминалось, целые числа - это целые числа. Они не могут сохранить точку, например .7, .42 и .007. Если вам нужно хранить числа, которые не являются целыми числами, вам понадобится другой тип переменной. Вы можете использовать двойной или плавающий тип. Вы устанавливаете эти типы переменных точно так же: вместо слова int
вы вводите double
или float
. Нравится:
float myFloat;
double myDouble;
(float
- это сокращение от «плавающая запятая» и означает просто число с точкой на конце.)
Разница между ними заключается в размере чисел, которые они могут вместить. Для float
вы можете иметь до 7 цифр в своем номере. Для double
вы можете иметь до 16 цифр. Если быть более точным, вот официальный размер:
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
float
- 32-битное число, а double
- 64-битное число.
Дважды щелкните новую кнопку, чтобы получить код. Добавьте в код кнопки следующие три строки:
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
Остановите вашу программу и вернитесь в окно кодирования. Измените эту строку:
myDouble = 0.007;
myDouble = 12345678.1234567;
Запустите вашу программу и нажмите двойную кнопку. В окне сообщения номер правильно отображается. Однако добавьте еще одно число в конце, и C # снова округлится в большую или меньшую сторону. Мораль такова: если вам нужна точность, будьте осторожны с округлением!
- Double и float можно без исключения разделить на целое число ноль как во время компиляции, так и во время выполнения.
- Десятичное число нельзя делить на целое число ноль. Компиляция всегда будет неудачной, если вы это сделаете.
- float: от ± 1,5 x 10 ^ -45 до ± 3,4 x 10 ^ 38 (~ 7 значащих цифр
- двойной: от ± 5,0 x 10 ^ -324 до ± 1,7 x 10 ^ 308 (15-16 значащих цифр)
- десятичный: от ± 1,0 x 10 ^ -28 до ± 7,9 x 10 ^ 28 (28-29 значащих цифр)
Типы переменных Decimal, Double и Float различаются способом хранения значений. Точность - это основное различие, где float - это тип данных с плавающей запятой одинарной точности (32 бита), double - тип данных с плавающей запятой двойной точности (64 бита), а decimal - это тип данных с плавающей запятой длиной 128 бит.
Float - 32 бит (7 цифр)
Двойной - 64 бит (15-16 цифр)
Десятичный - 128 бит (28-29 значащих цифр)
Подробнее о ... разнице между десятичным, плавающим и двойным
Это была интересная тема для меня, так как сегодня у нас только что произошла небольшая неприятная ошибка, касающаяся того, что decimal
имеет меньшую точность, чем float
.
В нашем коде C # мы читаем числовые значения из электронной таблицы Excel, конвертируем их в decimal
, а затем отправляем это decimal
обратно в службу для сохранения в SQL Server база данных.
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
Теперь для почти всех наших значений Excel это прекрасно сработало. Но для некоторых очень маленьких значений Excel использование decimal.TryParse
полностью потеряло значение. Одним из таких примеров является
cellValue = 0,00006317592
Decimal.TryParse (cellValue.ToString (), out value); // вернет 0
Как ни странно, решение заключалось в том, чтобы сначала преобразовать значения Excel в double
, а затем в decimal
:
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
Несмотря на то, что double
имеет меньшую точность, чем decimal
, это фактически гарантирует, что небольшие числа все равно будут распознаваться. По какой-то причине double.TryParse
действительно смог получить такие маленькие числа, тогда как decimal.TryParse
обнулял их.
Странный. Очень странно.
Для приложений, таких как игры и встроенные системы, где важны и память, и производительность, float обычно является числовым типом выбора, поскольку он быстрее и вдвое меньше double. Целые числа были предпочтительным оружием, но производительность с плавающей запятой в современных процессорах обогнала целые числа. Десятичная дробь прямо сейчас!
Проблема со всеми этими типами заключается в том, что существует некоторая неточность И что эта проблема может возникать с небольшими десятичными числами, как в следующем примере
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
Вопрос: Какое значение содержит переменная bLower?
Ответ: На 32-битной машине bLower содержит ИСТИНА !!!
Если я заменю Double на Decimal, bLower будет содержать FALSE, что является хорошим ответом.
В двойном случае проблема в том, что fMean-fDelta = 1.09999999999, что ниже 1.1.
Предостережение: я думаю, что такая же проблема, безусловно, может существовать для другого числа, потому что Decimal - это только double с более высокой точностью, а точность всегда имеет предел.
Фактически, Double, Float и Decimal соответствуют десятичной системе BINARY в COBOL!
К сожалению, других числовых типов, реализованных в COBOL, нет в .Net. Для тех, кто не знает COBOL, в COBOL существует следующий числовой тип
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
Простыми словами:
- Типы переменных Decimal, Double и Float различаются способом хранения значений.
- Точность - это основное отличие (обратите внимание, что это не единственное отличие), где float - это тип данных с плавающей запятой одинарной точности (32 бита). , double - это тип данных с плавающей запятой двойной точности (64 бит), а decimal - это 128-битный тип данных с плавающей запятой.
- Сводная таблица:
/==========================================================================================
Type Bits Have up to Approximate Range
/==========================================================================================
float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38)
double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
Вот
Терка
Двойной
Десятичная дробь
Десятичный 128 бит (28–29 значащих цифр) В случае финансовых приложений лучше использовать Десятичные типы, поскольку они обеспечивают высокий уровень точности и позволяют избежать ошибок округления. Используйте десятичную дробь для нецелочисленной математики, где требуется точность (например, деньги и валюта)
Double 64-бит (15–16 цифр) Двойные типы, вероятно, являются наиболее часто используемым типом данных для реальных значений, за исключением обработки денег. Используйте double для нецелочисленной математики, когда нет необходимости в наиболее точном ответе.
с плавающей запятой 32-бит (7 цифр) Он используется в основном в графических библиотеках, потому что очень высокие требования к вычислительной мощности, также используются ситуации, в которых могут возникать ошибки округления.
Decimals
намного медленнее, чем double/float
.
Decimals
и Floats/Doubles
нельзя сравнивать без приведения, тогда как Floats
и Doubles
можно.
Decimals
также разрешает кодировку или завершающие нули.
Основное различие между ними - точность.
float
- это число 32-bit
, double
- это число 64-bit
, а decimal
- это число 128-bit
.
Определение Decimal, Float и Double в .Net (c #)
Вы должны указать значения как:
Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;
И проверьте результаты.
И байты, занимаемые каждым, равны
Float - 4
Double - 8
Decimal - 12
Похожие вопросы
Новые вопросы
.net
НЕ используйте для вопросов о .NET Core - используйте вместо этого [.net-core]. .NET Framework - это программная среда, предназначенная главным образом для операционной системы Microsoft Windows. Он включает в себя реализацию библиотеки базовых классов, общеязыковой среды выполнения (обычно называемой CLR), общей системы типов (обычно называемой CTS) и динамической среды исполнения. Он поддерживает множество языков программирования, включая C #, VB.NET, F # и C ++ / CLI.