В чем разница decimal
, float
и double
в .NET?
Когда кто-нибудь будет использовать один из них?
.net
floating-point
double
decimal
ПК Luddite
источник
источник
Ответы:
float
иdouble
являются типами с плавающей двоичной точкой . Другими словами, они представляют число как это:Двоичное число и местоположение двоичной точки кодируются в пределах значения.
decimal
является плавающей десятичной точки типа . Другими словами, они представляют число как это:Опять же, число и местоположение десятичной точки оба закодированы в пределах значения - это то, что делает
decimal
тип с плавающей запятой все еще вместо типа с фиксированной запятой.Важно отметить, что люди привыкли представлять нецелые числа в десятичной форме и ожидать точных результатов в десятичных представлениях; не все десятичные числа точно представимы в двоичной переменной с плавающей запятой - например, 0,1 - поэтому, если вы используете двоичное значение с плавающей запятой, вы фактически получите приближение к 0,1. При использовании плавающей десятичной точки вы все равно получите приближения - например, результат деления 1 на 3 не может быть точно представлен.
Что касается того, что использовать, когда:
Для значений, которые являются «естественно точными десятичными числами», это хорошо использовать
decimal
. Обычно это подходит для любых концепций, изобретенных людьми: наиболее очевидным примером являются финансовые ценности, но есть и другие. Возьмем, к примеру, оценку, которую дают дайверам или фигуристам.Для значений, которые являются более артефактами природы, которые в любом случае не могут быть точно измерены ,
float
/double
являются более подходящими. Например, научные данные обычно представляются в такой форме. Здесь исходные значения не будут «десятично точными» для начала, поэтому для ожидаемых результатов не важно поддерживать «десятичную точность». Типы с плавающей двоичной точкой работают намного быстрее, чем десятичные.источник
float
/double
обычно не представляют числа как101.101110
, обычно это представляется как что-то вроде1101010 * 2^(01010010)
экспонентыfloat
это псевдоним C # и не тип .Net. этоSystem.Single
..single
иdouble
с плавающей точкой двоичные типы.Точность - это главное отличие.
Float - 7 цифр (32 бита)
Двойной -15-16 цифр (64 бит)
Десятичное число -28-29 значащих цифр (128 бит)
Десятичные дроби имеют гораздо более высокую точность и обычно используются в финансовых приложениях, которые требуют высокой степени точности. Десятичные дроби намного медленнее (в некоторых тестах до 20 раз), чем double / float.
Десятичные числа и числа с плавающей запятой / удвоения нельзя сравнивать без приведения, тогда как числа с числами с плавающей запятой и числами с удвоением Десятичные дроби также допускают кодирование или конечные нули.
Результат:
источник
0.1
- это редко имеет место в реальном мире! Любой конечный формат хранения будет сопоставлять бесконечное число возможных значений с конечным числом битовых комбинаций. Например,float
будет сопоставлять0.1
и0.1 + 1e-8
, покаdecimal
будет сопоставлять0.1
и0.1 + 1e-29
. Конечно, в пределах данного диапазона определенные значения могут быть представлены в любом формате с нулевой потерей точности (например,float
может хранить любое целое число до 1.6e7 с нулевой потерей точности) - но это все еще не бесконечная точность.0.1
это не особая ценность ! Единственное, что делает0.1
«лучше»,0.10000001
это то, что люди любят основу 10. И даже соfloat
значением, если вы инициализируете два значения0.1
одним и тем же способом, они оба будут иметь одинаковое значение . Просто это значение не будет точно0.1
- это будет самое близкое значение,0.1
которое может быть точно представлено какfloat
. Конечно, с двоичными числами,(1.0 / 10) * 10 != 1.0
но с десятичными числами(1.0 / 3) * 3 != 1.0
тоже. Ни не вполне точным.double a = 0.1; double b = 0.1;
тогдаa == b
будете верно . Это просто , чтоa
иb
будет и не совсем равны0.1
. В C #, если вы это сделаете,decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;
тоa == b
также будет верно. Но в этом случае, ни в ,a
ниb
будет точно равно1/3
- они оба равны0.3333...
. В обоих случаях некоторая точность теряется из-за представления. Вы упорно говорят , чтоdecimal
имеет «бесконечную» точность, которая является ложным .Десятичная структура строго ориентирована на финансовые расчеты, требующие точности, которые относительно нетерпимы к округлению. Однако десятичные дроби не подходят для научных приложений по нескольким причинам:
источник
Смотрите здесь для получения дополнительной информации .
источник
Я не буду повторять тонны хорошей (и некоторой плохой) информации, на которую уже даны ответы в других ответах и комментариях, но я отвечу на ваш дополнительный вопрос с подсказкой:
Используйте десятичную для подсчитанных значений
Используйте float / double для измеренных значений
Некоторые примеры:
деньги (мы считаем деньги или измеряем деньги?)
расстояние (мы считаем расстояние или измеряем расстояние? *)
баллы (мы считаем баллы или измеряем баллы?)
Мы всегда считаем деньги и никогда не должны их измерять. Мы обычно измеряем расстояние. Мы часто подсчитываем баллы.
* В некоторых случаях, что я бы назвал номинальным расстоянием , мы действительно можем рассчитывать расстояние. Например, возможно, мы имеем дело со знаками стран, которые показывают расстояния до городов, и мы знаем, что на этих расстояниях никогда не бывает больше одной десятичной цифры (ххх.х км).
источник
float
7 цифр точностиdouble
имеет около 15 цифр точностиdecimal
имеет около 28 цифр точностиЕсли вам нужна лучшая точность, используйте double вместо float. В современных процессорах оба типа данных имеют практически одинаковую производительность. Единственное преимущество использования поплавка - они занимают меньше места. Практически имеет значение, только если у вас их много.
Я нашел это интересно. Что каждый компьютерщик должен знать об арифметике с плавающей точкой
источник
double
правильным в приложениях учета в тех случаях (и в основном только в тех случаях), где не было доступно ни одного целочисленного типа больше 32 бит, иdouble
он использовался так, как если бы это был 53-битный целочисленный тип (например, для хранения). целое количество копеек или целых сотых процента). В наши дни такие вещи не слишком полезны, но многие языки получили возможность использовать значения с плавающей запятой двойной точности задолго до того, как они получили 64-битную (или в некоторых случаях даже 32-битную) целочисленную математику.Real
IIRC мог представлять значения до 1,8E + 19 с точностью до единицы. Я думаю, что было бы гораздо разумнее использовать бухгалтерское приложение дляReal
представления целого числа копеек, чем ...double
тип с единичной точностью до 9E15. Если нужно хранить целые числа, которые больше, чем самый большой доступный целочисленный тип, использованиеdouble
будет более простым и эффективным, чем попытка выдумать математику с высокой точностью, особенно если учесть, что у процессоров есть инструкции для выполнения 16x16-> 32 или. ..Никто не упомянул, что
я имею в виду
выдает OverflowException .
Но это не так:
&
источник
float.MaxValue+1 == float.MaxValue
, просто какdecimal.MaxValue+0.1D == decimal.MaxValue
. Возможно, вы имели в виду нечто подобноеfloat.MaxValue*2
?System.Decimal
Бросает исключение как раз перед его становится не в состоянии различать целые единицы, но если приложение должно иметь дело, например , с долларами и центами, что может быть слишком поздно.источник
decimal
на ноль (CS0020), и то же самое верно для целочисленных литералов. Однако, если десятичное значение времени выполнения делится на ноль, вы получите исключение, а не ошибку компиляции.Целые числа, как уже упоминалось, являются целыми числами. Они не могут хранить что-то, например, 0,7, 42 и 0,007. Если вам нужно хранить числа, которые не являются целыми числами, вам нужен другой тип переменной. Вы можете использовать тип double или тип float. Вы устанавливаете эти типы переменных точно таким же образом: вместо использования слова
int
вы вводитеdouble
илиfloat
. Нравится:(
float
сокращение от «с плавающей точкой», и просто означает число с точкой на конце.)Разница между ними заключается в размере чисел, которые они могут хранить. Например
float
, в вашем номере может быть до 7 цифр. Заdouble
s вы можете иметь до 16 цифр. Чтобы быть более точным, вот официальный размер:float
это 32-битное число, иdouble
64-разрядное число.Дважды щелкните новую кнопку, чтобы получить код. Добавьте следующие три строки в код вашей кнопки:
Остановите вашу программу и вернитесь в окно кодирования. Измените эту строку:
Запустите вашу программу и нажмите двойную кнопку. В окне сообщения правильно отображается номер. Добавьте еще один номер в конце, и C # снова округлит вверх или вниз. Мораль в том, что если вы хотите аккуратности, будьте осторожны с округлением!
источник
источник
decimal
фактически хранится в десятичном формате (в отличие от базы 2; поэтому он не будет терять или округлять цифры из-за преобразования между двумя числовыми системами); кроме того,decimal
не имеет понятия специальных значений, таких как NaN, -0, ∞ или -∞.Это была интересная тема для меня, так как сегодня у нас только что была маленькая неприятная ошибка, связанная
decimal
с меньшей точностью, чем уfloat
.В нашем коде C # мы читаем числовые значения из электронной таблицы Excel, преобразуем их в a
decimal
, а затем отправляемdecimal
обратно в службу для сохранения в базе данных SQL Server .Теперь, почти для всех наших значений Excel, это работало прекрасно. Но для некоторых очень маленьких значений Excel использование полностью
decimal.TryParse
потеряно. Одним из таких примеров являетсяcellValue = 0.00006317592
Decimal.TryParse (cellValue.ToString (), выходное значение); // вернет 0
Как ни странно, решением было преобразовать значения Excel в
double
первое, а затем вdecimal
:Несмотря на то, что
double
имеет меньшую точность, чем adecimal
, это фактически гарантировало, что небольшие числа все равно будут распознаваться. По какой-то причинеdouble.TryParse
удалось действительно получить такие небольшие числа, тогда какdecimal.TryParse
установил бы их на ноль.Странный. Очень странно.
источник
decimal.Parse("0.00006317592")
работает - у тебя что-то еще происходит. - Возможно, научная запись?Для приложений, таких как игры и встроенные системы, где память и производительность имеют решающее значение, float обычно является числовым типом выбора, так как он быстрее и вдвое меньше двойного. Раньше целое число было оружием выбора, но производительность с плавающей запятой превысила целое число в современных процессорах. Десятичный прямо сейчас!
источник
Переменные типа Decimal, Double и Float отличаются тем, как они хранят значения. Точность является основным отличием, когда float - это тип данных с плавающей запятой одинарной точности (32 бита), double - тип данных с плавающей запятой двойной точности (64 бита), а decimal - тип данных 128-битной плавающей запятой.
Float - 32 бита (7 цифр)
Двойной - 64 бит (15-16 цифр)
Десятичное число - 128 бит (28-29 значащих цифр)
Подробнее о ... разница между десятичной, плавающей и двойной
источник
Проблема со всеми этими типами заключается в том, что существует определенная неточность И что эта проблема может возникать с небольшими десятичными числами, как в следующем примере
Вопрос: Какое значение содержит переменная bLower?
Ответ: На 32-битной машине bLower содержит TRUE !!!
Если я заменю Double на Decimal, bLower содержит FALSE, что является хорошим ответом.
В двойном, проблема в том, что fMean-fDelta = 1.09999999999, что ниже, чем 1.1.
Предостережение: я думаю, что та же самая проблема, безусловно, может существовать для другого числа, потому что десятичная дробь - это только двойное число с более высокой точностью, а точность всегда имеет предел.
Фактически, Double, Float и Decimal соответствуют двоичному десятичному числу в COBOL!
К сожалению, другие числовые типы, реализованные в COBOL, не существуют в .Net. Для тех, кто не знает COBOL, существует в COBOL следующий числовой тип
источник
Простыми словами:
источник
Decimal
подходит для финансовых приложений и является основным критерием при выборе междуDecimal
иDouble
.Double
Например , редко бывает недостаточно точности для научных приложений (иDecimal
часто не подходит для научных приложений из-за ограниченного диапазона).Основным отличием каждого из них является точность.
float
это32-bit
число,double
это64-bit
число иdecimal
это128-bit
число.источник
Десятичное число 128 бит (28-29 значащих цифр). В финансовых приложениях лучше использовать десятичные типы, потому что это дает вам высокий уровень точности и легко избежать ошибок округления. Используйте десятичную для нецелочисленной математики, где требуется точность (например, деньги и валюта)
Двойные 64-битные (15-16 цифр) двойные типы, вероятно, являются наиболее обычно используемым типом данных для реальных значений, за исключением обработки денег. Используйте double для нецелочисленной математики, где не требуется самый точный ответ.
32-разрядное число с плавающей запятой (7 цифр). Используется главным образом в графических библиотеках, поскольку очень высоки требования к вычислительной мощности, а также используются ситуации, которые могут выдержать ошибки округления.
Decimals
намного медленнее, чемdouble/float
.Decimals
иFloats/Doubles
не может быть сравнен без броска, тогда какFloats
иDoubles
может.Decimals
также разрешить кодирование или конечные нули.источник
Чтобы определить десятичные, плавающие и двойные в .Net (c #)
Вы должны упомянуть значения как:
и проверьте результаты.
И байты, занятые каждым
источник