Подтвердить что ты не робот

Byte [] для неподписанного BigInteger?

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

Я могу конвертировать byte [] в BigInteger в С#...
Пример из того, что я имею до сих пор:

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

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

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

  • (A): как подписанный номер
  • (B): как число без знака

Можно ли сделать неподписанный BigInteger из байта [] в С#?

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

[...]

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

[...]

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

Ответ 3

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

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

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

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

Ответ 4

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

Согласно структуре MSDN BigInteger (System.Numerics)

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

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

byte[] byteArray;
// ...
var bigInteger = new BigInteger(byteArray.Concat(new byte[] { 0 }).ToArray());

Ответ 5

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

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

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

Ответ 6

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