Преобразовать байтовый массив (шестнадцатеричный) в знаковый Int - PullRequest
2 голосов
/ 19 февраля 2020

Я пытаюсь преобразовать шестнадцатеричную строку (переменной длины) в целое число со знаком (мне нужны положительные или отрицательные значения).

[Int16] [int 32] и [int64] кажется, что отлично работает с шестнадцатеричными строками длиной 2,4 байт, но я застрял с 3-байтовыми строками [int24] ( нет такой команды в powershell ).

Вот что у меня сейчас (фрагмент):

$start = $mftdatarnbh.Substring($DataRunStringsOffset+$LengthBytes*2+2,$StartBytes*2) -split "(..)"
[array]::reverse($start)
$start = -join $start

if($StartBytes*8 -le 16){$startd =[int16]"0x$($start)"}
elseif($StartBytes*8 -in (17..48)){$startd =[int32]"0x$($start)"}
else{$startd =[int64]"0x$($start)"}

С приведенным выше кодом значение $ start «D35A71» дает «13851249» вместо «-2925967». Я попытался найти способ реализовать два дополнения, но заблудился. Есть ли простой способ сделать это правильно?

Заранее спасибо

Редактировать : По сути, я думаю, что мне нужно реализовать что-то вроде этого:
int num = (sbyte)array[0] << 16 | array[1] << 8 | array[2];
как видно здесь .

Только что попробовал это:

$start = "D35A71"<br> [sbyte]"0x$($start.Substring(0,2))" -shl 16 -bor "0x$($start.Substring(2,2))" -shl 8 -bor "0x$($start.Substring(4,2))"

, но, похоже, не получил правильный результат: - /

1 Ответ

3 голосов
/ 19 февраля 2020

К парсинг строки шестнадцатеричного числа как минус число вы можете использовать [bigint] (System.Numerics.BigInteger) :

# Since the most significant hex digit has a 1 as its most significant bit
# (is >= 0x8), it is parsed as a NEGATIVE number.
# To force unconditional interpretation as a positive number, prepend '0'
# to the input hex string.
PS> [bigint]::Parse('D35A71', 'AllowHexSpecifier')
-2925967

Вы можете преобразовать полученный экземпляр [bigint] обратно в [int] (System.Int32).

Примечание:

  • Результатом является отрицательное число, поскольку старшее шестнадцатеричное число di git входной шестнадцатеричной строки равно >= 0x8, то есть имеет старший бит установлен .

    • Чтобы заставить [bigint] безоговорочно интерпретировать гекс. входная строка в виде положительного числа, предварения 0.
  • внутреннего дополнения до двух представление результирующего отрицательного числа выполняется при байт границы , так что заданное шестнадцатеричное число с нечетным числом цифр (т.е. если первый шестнадцатеричный ди git - это "полубайт") пропущенный полубайт заполнен 1 битами.

    • Следовательно, строка с шестнадцатеричным числом, наиболее значимый из которой ди git равно >= 0x8 (анализируется как отрицательное число) приводит к тому, что такое же число, что и при добавлении один или несколько F с (0xF = = 1111) к нему ; например, следующие вызовы все приводят к -2048:
      [bigint]::Parse('800', 'AllowHexSpecifier'),
      [bigint]::Parse('F800', 'AllowHexSpecifier'),
      [bigint]::Parse('FF800', 'AllowHexSpecifier'), ...

См. документы для получения подробной информации о логах разбора c.


Примеры:

# First digit (7) is < 8 (high bit NOT set) -> positive number
[bigint]::Parse('7FF', 'AllowHexSpecifier') # -> 2047

# First digit (8) is >= 8 (high bit IS SET) -> negative number
[bigint]::Parse('800', 'AllowHexSpecifier') # -> -2048

# Prepending additional 'F's to a number that parses as 
# a negative number yields the *same* result
[bigint]::Parse('F800', 'AllowHexSpecifier') # -> -2048
[bigint]::Parse('FF800', 'AllowHexSpecifier') # -> -2048
# ...

# Starting the hex-number string with '0' 
# *unconditionally* makes the result a *positive* number
[bigint]::Parse('0800', 'AllowHexSpecifier') # -> 2048
...