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




8 Answers

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

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

Double -15-16 цифр (64 бит)

Decimal -28-29 значащих цифр (128 бит)

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

Десятичные числа и поплавки / парные пары не могут сравниваться без броска, тогда как Floats and Doubles могут. Десятичные числа также допускают кодирование или конечные нули.

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
double отличие c#

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

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




+---------+----------------+---------+----------+---------------------------------------------+
| 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




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

В настройках по умолчанию 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;



  1. Двойной и float можно разделить на целые числа без исключения как для компиляции, так и для времени выполнения.
  2. Десятичное число нельзя делить на целое число. Компиляция всегда будет терпеть неудачу, если вы это сделаете.



Это была интересная тема для меня, так как сегодня у нас просто была неприятная небольшая ошибка, касающаяся 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); // вернет 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 обычно является числовым типом выбора, поскольку он быстрее и вдвое меньше двойного. Целые были предпочтительным оружием, но производительность с плавающей запятой превосходила целое число в современных процессорах. Десятичное право!




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

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) 



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

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




Related