Разница между decimal, float и double в .NET?
-
03-07-2019 - |
Вопрос
В чем разница между decimal
, float
и double
в .NET?
Когда бы кто-нибудь воспользовался одним из них?
Решение
float
и double
являются плавающий двоичный код типы точек.Другими словами, они представляют собой такое число, как это:
10001.10010110011
Двоичное число и местоположение двоичной точки кодируются внутри значения.
decimal
является плавающий десятичная дробь тип точки.Другими словами, они представляют собой такое число, как это:
12345.65789
Опять же, количество и местоположение десятичная дробь точки оба закодированы внутри значения – вот что делает decimal
по-прежнему используется тип с плавающей запятой вместо типа с фиксированной запятой.
Важно отметить, что люди привыкли представлять нецелые числа в десятичной форме и ожидают точных результатов в десятичных представлениях;не все десятичные числа точно представимы в двоичной форме с плавающей запятой – например, 0.1, – поэтому, если вы используете двоичное значение с плавающей запятой, вы фактически получите приближение к 0.1.Вы все равно получите приблизительные значения и при использовании десятичной запятой с плавающей запятой - например, результат деления 1 на 3 не может быть точно представлен.
Что касается того, что использовать, когда:
Для значений, которые являются "естественно точными десятичными дробями", полезно использовать
decimal
.Обычно это подходит для любых концепций, изобретенных людьми:финансовые ценности - самый очевидный пример, но есть и другие.Возьмем, к примеру, оценку, полученную ныряльщикам или конькобежцам.Для ценностей, которые в большей степени являются артефактами природы, которые на самом деле невозможно измерить именно так в любом случае,
float
/double
являются более подходящими.Например, научные данные обычно представляются в такой форме.Здесь исходные значения для начала не будут "десятичными", поэтому для ожидаемых результатов не важно поддерживать "десятичную точность".С типами двоичных чисел с плавающей запятой работать намного быстрее, чем с десятичными дробями.
Другие советы
Точность - главное отличие. Р>
Float - 7 цифр (32 бита) р>
Двойные -15-16 цифр (64-разрядные) р>
Десятичный -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
Десятичная структура строго ориентирована на финансовые расчеты, требующие точности, которые относительно нетерпимы к округлению.Однако десятичные дроби не подходят для научных приложений по нескольким причинам:
- Определенная потеря точности допустима во многих научных расчетах из-за практических ограничений измеряемой физической проблемы или артефакта.Потеря точности недопустима в финансах.
- Decimal намного (намного) медленнее, чем float и double для большинства операций, в первую очередь потому, что операции с плавающей запятой выполняются в двоичном формате, тогда как десятичный материал выполняется в базе 10 (т. Е.числа с плавающей запятой и удвоения обрабатываются аппаратными средствами FPU, такими как MMX / SSE, в то время как десятичные дроби вычисляются программным путем).
- Decimal имеет недопустимо меньший диапазон значений, чем double, несмотря на то, что он поддерживает большее количество цифр точности.Следовательно, десятичная дробь не может использоваться для представления многих научных значений.
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
Для получения дополнительной информации см .:
http: //social.msdn .microsoft.com / Форум / EN-US / csharpgeneral / резьба / 921a8ffc-9829-4145-bdc9-a96c1ec174a5
float
7 цифр точности
double
имеет точность около 15 цифр
decimal
имеет точность около 28 цифр
Если вам нужна лучшая точность, используйте double вместо float. В современных процессорах оба типа данных имеют практически одинаковую производительность. Единственное преимущество использования поплавка - они занимают меньше места. Практически имеет значение, только если у вас их много.
Я обнаружил, что это интересно. Что каждый ученый-компьютерщик должен знать об арифметике с плавающей запятой а> р>
Я не буду повторять тонны хорошей (и некоторой плохой) информации, на которую уже даны ответы в других ответах и комментариях, но я отвечу на ваш последующий вопрос советом:
Когда бы кто-нибудь воспользовался одним из них?
Используйте десятичную дробь для подсчитано ценности
Используйте float / double для измеренный ценности
Несколько примеров:
деньги (мы считаем деньги или измеряем их?)
расстояние (мы считаем расстояние или измеряем дистанцию?*)
баллы (мы подсчитываем баллы или измеряем баллы?)
Мы всегда считаем деньги и никогда не должны их измерять.Обычно мы измеряем расстояние.Мы часто подсчитываем баллы.
* В некоторых случаях то, что я бы назвал номинальное расстояние, возможно, мы действительно захотим "посчитать" расстояние.Например, возможно, мы имеем дело со знаками стран, которые показывают расстояния до городов, и мы знаем, что эти расстояния никогда не содержат более одной десятичной цифры (xxx.x км).
Никто не упоминал об этом
В настройках по умолчанию значения Float (System.Single) и doubles (System.Double) никогда не будут использоваться проверка переполнения, в то время как Decimal (System.Decimal) будет использоваться всегда проверка переполнения.
Я имею в виду
decimal myNumber = decimal.MaxValue;
myNumber += 1;
бросает Исключение OverflowException.
Но это не так:
float myNumber = float.MaxValue;
myNumber += 1;
&
double myNumber = double.MaxValue;
myNumber += 1;
Целые числа, как уже упоминалось, являются целыми числами. Они не могут хранить что-то, например, 0,7, 42 и 0,007. Если вам нужно хранить числа, которые не являются целыми числами, вам нужен другой тип переменной. Вы можете использовать тип double или тип float. Вы устанавливаете эти типы переменных точно таким же образом: вместо использования слова int
вы вводите double
или float
. Вот так:
float myFloat;
double myDouble;
( float
- сокращение от «quat; с плавающей запятой» и означает просто число с точкой на конце.)
Разница между ними заключается в размере чисел, которые они могут содержать. Для 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 # снова округлит вверх или вниз. Мораль такова: если хочешь аккуратности, будь осторожен с округлением!
Для меня это была интересная тема, так как сегодня у нас только что произошла неприятная маленькая ошибка, касающаяся decimal
имеющий меньшую точность, чем float
.
В нашем коде на C # мы считываем числовые значения из электронной таблицы Excel, преобразуя их в decimal
, затем отправив это decimal
вернуться к Сервису для сохранения в SQL Сервер База данных.
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
полностью утратил свою ценность.Одним из таких примеров является
Значение ячейки = 0.00006317592
Десятичный.Попробуйте проанализировать (значение ячейки.toString(), выходное значение); // вернул бы 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
установил бы их равными нулю.
Странно.Очень странно.
- плавать:от ±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 значащих цифр)
Для приложений, таких как игры и встроенные системы, где память и производительность имеют решающее значение, float обычно выбирается числовым типом, так как он быстрее и вдвое меньше двойного. Раньше целое число было оружием выбора, но производительность с плавающей запятой превысила целое число в современных процессорах. Десятичный сразу!
Типы переменных Decimal, Double и Float отличаются тем, как они хранят значения. Точность является основным отличием, когда float - это тип данных с плавающей запятой одинарной точности (32 бита), double - тип данных с плавающей запятой двойной точности (64 бита), а decimal - тип данных 128-битной плавающей запятой.
Float - 32 бита (7 цифр)
Двойной - 64 бит (15-16 цифр)
Десятичный - 128 бит (28-29 значащих цифр)
Подробнее о ... разнице между десятичным, плавающим и двойным р>
Проблема со всеми этими типами заключается в том, что существует определенная неточность И что эта проблема может возникнуть с маленькими десятичными числами, как в следующем примере
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 содержит TRUE !!!
Если я заменю Double на Decimal, bLower содержит FALSE, что является хорошим ответом.
В двойном случае проблема в том, что fMean-fDelta = 1.09999999999, что ниже, чем 1.1.
Предостережение: я думаю, что та же самая проблема, безусловно, может существовать для другого числа, потому что десятичная дробь - это всего лишь двойное число с более высокой точностью, а точность всегда имеет предел.
Фактически, Double, Float и Decimal соответствуют двоичному десятичному числу в 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)
Простыми словами:
<Ол>
/==========================================================================================
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)
/==========================================================================================
Вы можете прочитать больше здесь , Float , Double и десятичное число .
Основным отличием каждого из них является точность.
float
- это 32-разрядное
число, double
- это 64-разрядное
число и десятичное число
- это 128-битное
число.