Двоичное представление .NET Decimal

Как тип .NET decimal представляется в двоичной форме в памяти?

Все мы знаем, как хранятся числа с плавающей запятой, и, следовательно, причины их неточности, но я не могу найти никакой информации о decimal, кроме следующего:

  1. По-видимому, более точен, чем числа с плавающей запятой
  2. Занимает 128 бит памяти
  3. 2 ^ 96 + диапазон знаков
  4. 28 (иногда 29?) Всего значащих цифр в номере

Есть ли способ понять это? Ученый-компьютерщик во мне требует ответа, и после часа попыток исследования я не могу его найти. Похоже, либо много потраченного впустую битов, либо я просто неправильно представляю себе это в своей голове. Кто-нибудь может пролить свет на это, пожалуйста?


person Squirrelsama    schedule 27.09.2010    source источник


Ответы (2)


Decimal.GetBits для получения нужной информации.

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

Таким образом, для представления 3,261 у вас будет мантисса 3261, знаковый бит 0 (т. Е. Положительный) и показатель степени 3. Обратите внимание, что десятичная дробь не нормализована (намеренно), поэтому вы можете также представляют 3,2610, используя мантиссу 32610 и показатель степени 4, например.

У меня есть дополнительная информация в моей статье о десятичной плавающей запятой.

person Jon Skeet    schedule 27.09.2010
comment
+1 фантастический ответ, по существу и богатый информацией. - person JoshD; 27.09.2010
comment
@Jacob: Нет, это явно неправда. Учитывая, что вы можете начать с целого числа и закончить (скажем) 0,1, это, очевидно, сдвиг вправо. Если бы вы могли только сдвигаться влево, вы могли бы представлять 10, 100 и т. Д., Но не 0,1, 0,01 и т. Д. В будущем, пожалуйста, дождитесь подтверждения, прежде чем вы значительно измените значение ответа. нравится. См. Документацию для decimal: msdn.microsoft.com/en-us/library/ 1k2e8atx.aspx - где коэффициент масштабирования рассматривается как деление целого числа, что эквивалентно его сдвигу вправо. - person Jon Skeet; 13.02.2013
comment
Мои извенения. Для меня более интуитивно понятно думать об этом как о смещении десятичной точки в влево, но теперь я вижу, что вы имеете в виду смещение мантиссы. - person Jacob; 13.02.2013
comment
Из книги: «биты 16-23 (младшие биты старшего 16-битного слова) содержат показатель степени» - означает ли это, что показатель степени имеет 8 бит и, следовательно, можно сдвинуть вправо максимум 255 десятичных знаков? - person nalply; 21.04.2013
comment
@nalply: 8 бит фактически зарезервированы для экспоненты, но на нее установлен предел, поэтому диапазон фактически составляет всего 0-29. - person Jon Skeet; 21.04.2013
comment
Этот ответ делает его намного понятнее, чем в связанной статье. Несмотря на то, что в статье приводится точная формула, пример всегда удобен для понимания. - person Felix Dombek; 26.08.2015
comment
Итак, 96 бит для мантиссы и один бит для знака. Тогда я ожидал бы пять бит для экспоненты от 0 до 28, и я бы ожидал, что 26 неиспользованных битов дадут в общей сложности 128. Но согласно этой странице MSDN на самом деле есть только 23 неиспользуемых бита, потому что экспонента представлена ​​восемью бит вместо нужных пяти. Тогда я предполагаю, что три старших бита экспоненты не используются и тоже должны быть равны нулю? Или их просто игнорируют, если они не нулевые? - person Adam Goodwin; 09.02.2016
comment
@AdamGoodwin: Я бы не хотел догадываться, что произойдет, если они не равны нулю, хотя в документации для конструктора, принимающего составные части, говорится, что он выдает исключение, если масштаб больше 28. - person Jon Skeet; 09.02.2016

https://www.csharpindepth.com/Articles/Decimal

Как хранится десятичная дробь?

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

person Jevgenij    schedule 22.06.2019