Разница между десятичной, плавающей и двойной в .NET?

В чем разница между decimal, float и double в .NET?

Когда кто-нибудь воспользуется одним из них?

+1939
источник поделиться
18 ответов

float и double - это типы плавающих двоичных точек. Другими словами, они представляют собой число, подобное этому:

10001.10010110011

Двоичный номер и местоположение двоичной точки кодируются в пределах значения.

decimal - тип с плавающей запятой. Другими словами, они представляют собой число, подобное этому:

12345.65789

Опять же, число и местоположение десятичной точки оба закодированы внутри значения - то, что делает decimal типом еще тип с плавающей точкой вместо типа фиксированной точки.

Важно отметить, что люди используются для представления нецелых чисел в десятичной форме и ожидают точных результатов в десятичных представлениях; не все десятичные числа точно представлены в двоичной с плавающей запятой - 0,1, например, поэтому, если вы используете двоичное значение с плавающей запятой, вы фактически получите приближение к 0,1. Вы также получите приближения при использовании плавающей десятичной точки - результат деления 1 на 3 не может быть точно представлен, например.

Что касается того, что использовать, когда:

  • Для значений, которые являются "естественно точными десятичными знаками", полезно использовать decimal. Это обычно подходит для любых понятий, изобретенных людьми: финансовые показатели являются наиболее очевидным примером, но есть и другие. Рассмотрим, например, оценку дайверам или фигуристам.

  • Для значений, которые являются более артефактами природы, которые в действительности не могут быть точно измерены, float/double более подходят. Например, научные данные обычно представляются в этой форме. Здесь исходные значения не будут "децимально точными" для начала, поэтому для ожидаемых результатов не важно поддерживать "десятичную точность". Плавающие двоичные точечные типы намного быстрее работают, чем десятичные.

+2115
источник

Точность - это главное отличие.

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
+983
источник

Десятичная структура строго ориентирована на финансовые расчеты, требующие точности, которые относительно нетерпимы к округлению. Десятичные числа не подходят для научных приложений, однако по нескольким причинам:

  • Некоторая потеря точности приемлема во многих научных расчетах из-за практических пределов измеряемой физической проблемы или артефакта. Потеря точности не приемлема в финансах.
  • Десятичное значение намного (намного) медленнее, чем float и double для большинства операций, в первую очередь потому, что операции с плавающей запятой выполняются в двоичном формате, тогда как Decimal выполняется в базе 10 (т.е. поплавки и удваиваются обрабатываются оборудованием FPU, например MMX/SSE, тогда как десятичные числа вычисляются в программном обеспечении).
  • Десятичный имеет недопустимо меньший диапазон значений, чем двойной, несмотря на то, что он поддерживает больше цифр точности. Поэтому Decimal нельзя использовать для представления многих научных значений.
+76
источник
+---------+----------------+---------+----------+---------------------------------------------+
| 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/Forums/en-US/csharpgeneral/thread/921a8ffc-9829-4145-bdc9-a96c1ec174a5

+67
источник

float 7 цифр точности

double имеет около 15 цифр точности

decimal имеет около 28 цифр точности

Если вам нужна более высокая точность, используйте double вместо float. В современных процессорах оба типа данных имеют почти такую ​​же производительность. Единственное преимущество использования float - они занимают меньше места. Практически важно, только если у вас их много.

Я нашел это интересным. Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой

+45
источник

Я не буду повторять тонны хорошей (и некорректной) информации, на которую уже ответил ответ в других ответах и ​​комментариях, но я отвечу на ваш последующий вопрос с подсказкой:

Когда кто-нибудь воспользуется одним из них?

Используйте десятичное значение для подсчитанных значений

Использовать float/double для значений измеренных

Некоторые примеры:

  • деньги (мы считаем деньги или измеряем деньги?)

  • расстояние (рассчитываем расстояние или измеряем расстояние?)

  • (мы подсчитываем баллы или оцениваем баллы?)

Мы всегда считаем деньги и никогда не должны их измерять. Обычно мы измеряем расстояние. Мы часто подсчитываем баллы.

* В некоторых случаях, что я бы назвал номинальным расстоянием, мы можем действительно хотеть "подсчитать" расстояние. Например, возможно, мы имеем дело со знаками страны, которые показывают расстояния до городов, и мы знаем, что эти расстояния никогда не имеют более одной десятичной цифры (xxx.x км).

+39
источник

Никто не упомянул, что

В настройках по умолчанию Floats (System.Single) и double (System.Double) никогда не будут использовать проверка переполнения, в то время как Decimal (System.Decimal) всегда будет использовать проверка переполнения.

Я имею в виду

decimal myNumber = decimal.MaxValue;
myNumber += 1;

throws OverflowException.

Но это не так:

float myNumber = float.MaxValue;
myNumber += 1;

&

double myNumber = double.MaxValue;
myNumber += 1;
+34
источник
  • Двойные и float могут быть делятся на целые числа без исключения как для компиляции, так и для времени выполнения.
  • Десятичное число нельзя делить на целое число. Компиляция всегда будет терпеть неудачу, если вы это сделаете.
+27
источник

Целые числа, как уже упоминалось, являются целыми числами. Они не могут хранить точку, например.7,.42 и.007. Если вам нужно хранить числа, которые не являются целыми числами, вам нужен другой тип переменной. Вы можете использовать тип double или float. Вы устанавливаете эти типы переменных точно так же: вместо использования слова int вы вводите double или float. Как это:

float myFloat;
double myDouble;

(float подходит для "плавающей запятой" и просто означает число с точкой что-то в конце.)

Разница между ними - это размер чисел, которые они могут удерживать. Для float вы можете иметь до 7 цифр в своем номере. Для double s вы можете иметь до 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;

Запустите программу и нажмите двойную кнопку. В поле сообщения правильно отображается номер. Добавьте еще один номер в конец, и С# снова округляется вверх или вниз. Мораль - если вы хотите точности, будьте осторожны с округлением!

+27
источник

Типы переменных Decimal, Double и Float отличаются тем, что они сохраняют значения. Точность - основное отличие, в котором float представляет собой тип данных с плавающей точкой с одной точностью (32 бит), double - это тип данных с плавающей точкой с двойной точностью (64 бит), а десятичный - это тип данных с плавающей точкой с 128-разрядной точкой.

Float - 32 бит (7 цифр)

Двойной - 64 бит (15-16 цифр)

Десятичный - 128 бит (28-29 значащих цифр)

Основное различие заключается в том, что Float и Doubles представляют собой двоичные типы с плавающей запятой, а Decimal будет хранить значение в виде типа с плавающей запятой. Таким образом, Decimals имеют гораздо более высокую точность и обычно используются в денежных (финансовых) или научных приложениях расчета, которые требуют высокой степени точности. Но в производительности разумные Десятичные разряды медленнее, чем двойные и плавающие типы.

Decimal может 100% точно представлять любое число в пределах точности десятичного формата, тогда как Float и Double, не могут точно представлять все числа, даже числа, которые находятся в пределах их соответствующих форматов.

Decimal

В случае финансовых приложений или научных расчетов лучше использовать десятичные типы, потому что это дает вам высокий уровень точности и легко избежать ошибок округления.

Double

Двойные типы, вероятно, являются наиболее обычно используемым типом данных для реальных значений, за исключением обработки денег.

Float

Он используется в основном в графических библиотеках, потому что очень высокие требования к мощности обработки, а также используются ситуации, которые могут выдержать ошибки округления.

+27
источник

Это была интересная тема для меня, так как сегодня у нас просто была неприятная небольшая ошибка, касающаяся decimal чисел с меньшей точностью, чем float.

В нашем коде С# мы считываем числовые значения из электронной таблицы 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); // вернет 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 установил бы их в ноль.

Странно. Очень странно.

+13
источник
  • 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 значимых цифр)
+12
источник

Для приложений, таких как игры и встроенные системы, где важна память и производительность, float обычно является числовым типом выбора, поскольку он быстрее и вдвое меньше двойного. Целые были предпочтительным оружием, но производительность с плавающей запятой превосходила целое число в современных процессорах. Десятичное число прямо!

+8
источник

Типы переменных Decimal, Double и Float отличаются тем, что они сохраняют значения. Точность - основное отличие, в котором float представляет собой тип данных с плавающей точкой с одной точностью (32 бит), double - это тип данных с плавающей точкой с двойной точностью (64 бит), а десятичный - это тип данных с плавающей точкой с 128-разрядной точкой.

Float - 32 бит (7 цифр)

Двойной - 64 бит (15-16 цифр)

Десятичный - 128 бит (28-29 значащих цифр)

Подробнее... разница между десятичным, плавающим и двойным

+7
источник

Проблема со всеми этими типами заключается в том, что существует некоторая неточность И эта проблема может возникать с небольшими десятичными числами, как в следующем примере

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.

Предостережение: я думаю, что такая же проблема может существовать и для другого числа, потому что Decimal является только двойным с более высокой точностью, и точность всегда имеет предел.

Фактически, 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) 
+5
источник

Простыми словами:

  1. Типы переменных Decimal, Double и Float отличаются тем, что они сохраняют значения.
  2. Точность - основное различие (обратите внимание, что это не единственная разница), где float - это тип данных с плавающей точкой с одной точностью (32 бит), double - это тип данных с плавающей точкой с двойной точностью (64 бит), а десятичный - это 128-битный тип данных с плавающей точкой.
  3. Сводная таблица:

/==========================================================================================
    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)
/==========================================================================================
You can read more here, Float, Double, and Decimal.
+4
источник

Основное различие между каждым из них - точность.

float - это число 32-bit, double - это число 64-bit, а decimal - число 128-bit.

+3
источник

Посмотрите другие вопросы по меткам или Задайте вопрос