байт [] без знака BigInteger? - PullRequest
       26

байт [] без знака BigInteger?

24 голосов
/ 13 апреля 2011

Мотивация: Я хотел бы преобразовать хэши (MD5 / SHA1 и т. Д.) В десятичные целые числа с целью создания штрих-кодов в Code128C. Для простоты я предпочитаю, чтобы все полученные (большие) числа были положительными.

Я могу конвертировать байт [] в BigInteger в C # ...
Образец из того, что у меня так далеко:

byte[] data;
byte[] result;
BigInteger biResult;

result = shaM.ComputeHash(data);
biResult = new BigInteger(result);

Но (ржавый CS здесь) я прав, что байтовый массив всегда можно интерпретировать двумя способами: A: как подписанный номер B: как число без знака

Возможно ли сделать БЕЗИМИНЕР без знака из байта [] в C #?

Должен ли я просто добавить 0x00 (нулевой байт) перед байтом []?

EDIT: Спасибо AakashM, Джону и Адаму Робинсону, добавив нулевой байт, достиг того, что мне нужно. \

EDIT2: Главное, что я должен был сделать, это прочитать подробный документ конструктора BigInteger (byte []), тогда я бы увидел разделы о том, как ограничиться положительными числами, добавив нулевой байт.

Ответы [ 6 ]

34 голосов
/ 13 апреля 2011

Замечания для конструктора BigInteger означают, что вы можете убедиться, что любой BigInteger, созданный из byte[], не подписан, если вы добавите 00 байт в конец массив перед вызовом конструктора.

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

6 голосов
/ 13 апреля 2011

Изучая документацию для соответствующего BigInteger конструктора , мы видим:

Отдельные байты в массиве значений должны быть в little-endian порядок, от младшего байта к старшему байту

[...]

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

[...]

Для предотвращения положительных значенийиз-за неправильного толкования как отрицательных значений вы можете добавить нулевое байтовое значение к end массива.

5 голосов
/ 09 апреля 2015

Как указывалось в других ответах, вы должны добавить байт 00 в конец массива, чтобы убедиться, что полученный BigInteger положителен.

В соответствии с структурой BigInteger (System.Numerics) документации MSDN

Чтобы конструктор BigInteger (Byte []) не мог перепутать представление дополнения двух отрицательных значений с представлением знака и величины положительного значения, положительных значений, в котором старший значащий бит последнего байта в байтовом массиве обычно устанавливается, должен включать дополнительный байт со значением 0.

Вот код для этого:

byte[] byteArray;
// ...
var bigInteger = new BigInteger(byteArray.Concat(new byte[] { 0 }).ToArray());
5 голосов
/ 13 апреля 2011

Но (ржавый CS здесь) я прав, что байтовый массив всегда можно интерпретировать двумя способами: A: как число со знаком B: как число без знака

Более тоговерно то, что все числа (в силу того, что они хранятся в компьютере) в основном представляют собой последовательность байтов, то есть массив байтов.Неверно утверждать, что байтовый массив всегда можно интерпретировать как подписанную или неподписанную версию определенного числового типа, поскольку не все числовые типы имеют подписанную и неподписанную версии.Типы с плавающей точкой, как правило, имеют только подписанные версии (нет udouble или ufloat), и, в данном конкретном случае, не существует беззнаковой версии BigInteger.

Таким образом, другими словами, нет, это невозможно, но поскольку BigInteger может представлять произвольно большое целочисленное значение, вы не теряете никакого диапазона из-за его подписания.

Что касается вашего второго вопроса, вам необходимо добавить 0x00 до конца конец массива, так как конструктор BigInteger анализирует значения в порядке байтов с прямым порядком байтов.

2 голосов
/ 08 апреля 2018

Альтернативой является создание BigInteger с использованием вашего байтового массива, а затем использование Abs (эквивалентно Math.Abs), чтобы сделать его абсолютным значением:

var bi = new BigInteger(result);
var biPositive = BigInteger.Abs(bi1);

Технически вам требуется толькоиспользовать Abs, если bi отрицательно (например, если bi.Sign == -1)

0 голосов
/ 15 июля 2019

На момент написания этой статьи ctor для BigInteger теперь имеет необязательный параметр isUnsigned. (проверено для ядра .Net)

...