Как преобразовать System.Decimal биты в строку в C #? - PullRequest
5 голосов
/ 29 марта 2011

Я хотел бы иметь возможность получить биты из значения System.Decimal и затем преобразовать его в строковое представление значения, так же, как это сделал бы Decimal.ToString(), но мне трудно придумать алгоритм .

Итак, у меня есть что-то вроде этого:

decimal d = 1403.45433M;
int[] nDecimalBits = decimal.GetBits(d);

// How to convert the 4 integers in nDecimalBits to a string
// that contains "1403.45433"?

Я знаю двоичный формат десятичного числа - первые 3 целых числа содержат биты значения, а последнее целое число содержит бит знака и коэффициент масштабирования.

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

Любая помощь будет оценена.

Редактировать : в ответ на некоторые ответы мне нужно отправить биты на другую платформу, где необходимо восстановить значение. System.Decimal и любая из его функций-членов там недоступны, поэтому мне нужно взять биты и перевести их в строку.

Если бы у меня был выбор, я бы, очевидно, использовал ToString(), но тогда мне не нужно было бы спрашивать.

Ответы [ 4 ]

6 голосов
/ 29 марта 2011

Вы можете использовать конструктор Decimal Decimal (Int32 []) , чтобы преобразовать ваше значение обратно:

Десятичный конструктор (Int32 [])

Инициализирует новый экземпляр Decimal десятичным значением, представленным в двоичном формате и содержащимся в указанном массиве.

После этого вы можете использовать ToString, если хотите. Пример:

decimal d = 1403.45433M;
int[] nDecimalBits = decimal.GetBits(d);

decimal d2 = new decimal(nDecimalBits);
string s = d2.ToString();
4 голосов
/ 29 марта 2011

Это не алгоритм, но я полагаю, это должно помочь.

Десятичные биты структура :

Двоичное представление десятичного числа число состоит из 1-битного знака, 96-битное целое число и масштабирование коэффициент, используемый для деления целого числа номер и укажите, какая его часть является десятичной дробью. Масштабирование фактор неявно число 10, возведен в степень в диапазоне от 0 до 28.

Возвращаемое значение является четырехэлементным массив 32-битных целых чисел со знаком.

Первый, второй и третий элементы возвращаемого массива содержат минимум, средние и старшие 32 бита 96-битного целое число.

Четвертый элемент возвращен массив содержит масштабный коэффициент и знак. Состоит из следующих частей:

Биты от 0 до 15, нижнее слово, являются не используется и должен быть равен нулю.

Биты с 16 по 23 должны содержать показатель степени от 0 до 28, что указывает на сила 10, чтобы разделить целое число число.

Биты с 24 по 30 не используются и должны быть ноль.

Бит 31 содержит знак; 0 означает положительный, а 1 означает отрицательный.

2 голосов
/ 29 марта 2011

Есть ли какая-то основная причина, по которой вы не можете просто использовать десятичный конструктор?

1 голос
/ 30 марта 2011

Поскольку вы не можете использовать ToString(), вы можете проверить, как разработчики моно реализовали это:

Точка входа: NumberToString (строка, десятичное число, IFormatProvider) .

Интересная часть - InitDecHexDigits (uint, ulong) , которая вызывается так

InitDecHexDigits ((uint)bits [2], ((ulong)bits [1] << 32) | (uint)bits [0]);

и выполняет «битовое жонглирование и сдвиг», чтобы преобразовать три целых числа в двоично-десятичные десятичные числа (_val1 в _val4), что может быть (тривиально) ) преобразуется в строку.

(Не смущайтесь тем, что они называют его "шестнадцатеричным представлением". Это двоичное кодирование десятичное цифр.)

...