За кулисами, что происходит с десятичным типом значения в C#/.NET?

Как реализован тип decimal?

Обновить

  • Это 128-битный тип значения (16 байт).
  • 1 знаковый бит
  • 96 бит (12 байт) для мантиссы
  • 8 бит для экспоненты
  • оставшиеся биты (из них 23!) установлены в 0

Спасибо! Я буду придерживаться 64-битной длины с моим собственным подразумеваемым масштабом.


person Haywood Jablomey    schedule 20.07.2010    source источник


Ответы (6)


Статья Десятичные числа с плавающей запятой в Википедии с конкретной ссылкой на эту статью о System.Decimal.

Десятичное число хранится в 128 битах, хотя строго необходимы только 102. Десятичное число удобно рассматривать как три 32-битных целых числа, представляющих мантиссу, а затем одно целое число, представляющее знак и показатель степени. Верхний бит последнего целого числа является битом знака (обычным способом, когда бит устанавливается (1) для отрицательных чисел), а биты 16-23 (младшие биты старшего 16-битного слова) содержат показатель степени. Все остальные биты должны быть очищены (0). Это представление задается decimal.GetBits(decimal), которое возвращает массив из 4 целых чисел.

person Jesse Dhillon    schedule 20.07.2010
comment
Связанная статья была полезной; этот г-н Скит кажется надежным источником вопросов, связанных с С#. У него много познавательных статей. - person Haywood Jablomey; 21.07.2010

Из Спецификаций языка C#:

Тип decimal представляет собой 128-битный тип данных, подходящий для финансовых и денежных расчетов.
Тип decimal может представлять значения в диапазоне от 1,0 × 10−28 до приблизительно 7,9 × 1028<. /sup> с 28-29 значащими цифрами.

Конечное множество значений типа decimal имеет вид (–1)s × c × 10-e , где знак s равен 0 или 1, коэффициент c определяется как 0 ≤ c ‹ 2 96, а шкала e такова, что 0 ≤ e ≤ 28.
Тип decimal не поддерживает знаковые нули, бесконечности, или NaN. decimal представляется как 96-битное целое число, масштабированное в степени 10. Для десятичных дробей с абсолютным значением менее 1,0 м значение точно до 28го десятичного знака, но не дальше.

Для десятичных дробей с абсолютным значением, большим или равным 1,0 м, значение является точным до 28 или 29 цифр. В отличие от типов данных float и double, десятичные дробные числа, такие как 0,1, могут быть представлены точно в десятичном представлении. В представлениях float и double такие числа часто являются бесконечными дробями, что делает эти представления более подверженными ошибкам округления.

Если один из операндов бинарного оператора имеет тип decimal, то другой операнд должен быть целочисленного типа или типа decimal. Если присутствует операнд целочисленного типа, он преобразуется в decimal перед выполнением операции.

Результатом операции над значениями типа decimal является результат вычисления точного результата (с сохранением масштаба, определенного для каждого оператора) и последующего округления до соответствия представлению. Результаты округляются до ближайшего представимого значения и, если результат одинаково близок к двум представимым значениям, до значения, которое имеет четное число в младшей значащей позиции (это называется «банковским округлением»). Нулевой результат всегда имеет знак 0 и шкалу 0.

Если десятичная арифметическая операция дает значение, меньшее или равное 5 × 10-29 по абсолютной величине, результат операции становится равным нулю. Если десятичная арифметическая операция дает результат, который слишком велик для формата decimal, выдается System.OverflowException.

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

person Bertrand Marron    schedule 20.07.2010

Как описано на странице десятичной структуры MSDN по адресу http://msdn.microsoft.com/en-us/library/system.decimal(VS.80).aspx:

Двоичное представление значения Decimal состоит из 1-битного знака, 96-битного целого числа и коэффициента масштабирования, используемого для деления 96-битного целого числа и указания того, какая его часть является десятичной дробью. Коэффициент масштабирования неявно представляет собой число 10, возведенное в степень в диапазоне от 0 до 28. Таким образом, двоичное представление десятичного значения имеет вид ((-296 до 296)/10(0 до 28)), где -296-1 равно MinValue, а 296-1 равно MaxValue.

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

person Scott Stafford    schedule 20.07.2010

Из третьего издания "CLR через С#" Дж. Рихтера:

128-битное высокоточное значение с плавающей запятой, обычно используемое для финансовых расчетов, в которых недопустимы ошибки округления. Из 128 бит 1 бит представляет знак значения, 96 бит представляют само значение, а 8 бит представляют степень 10, на которую нужно разделить 96-битное значение (может быть где угодно от 0 до 28). Остальные биты не используются.

person Otávio Décio    schedule 20.07.2010

Ключевое слово decimal обозначает 128-битный тип данных.

Источник

Двоичное представление значения Decimal состоит из 1-битного знака, 96-битного целого числа и коэффициента масштабирования, используемого для деления 96-битного целого числа и указания того, какая его часть является десятичной дробью. Коэффициент масштабирования неявно представляет собой число 10, возведенное в степень в диапазоне от 0 до 28. Таким образом, двоичное представление десятичного значения имеет вид ((-296 до 296)/10(0 до 28)), где -296-1 равно MinValue, а 296-1 равно MaxValue.

Источник

person ChrisF    schedule 20.07.2010

Десятичный тип — это просто еще одна форма числа с плавающей запятой, но в отличие от float и double используемая база равна 10.

Простое объяснение находится здесь http://csharpindepth.com/Articles/General/Decimal.aspx

person Sharjeel Aziz    schedule 20.07.2010