Неожиданные результаты распаковки с битовыми строками

почему это, когда я открываю irb и запускаю
puts 'A'.unpack("B8")
Я получаю 01000001 но когда я запускаю
puts 'A'.unpack("B4B4")
Я только 0100, а не [0100,0001]?

является ли разрешение распаковки только полным байтом? Не меньше?

1 ответов


давайте сделаем несколько тестов, чтобы понять поведение:

> 'A'.unpack('B8')
 => ["01000001"] 

он возвращает 8 наиболее значимых битов (MSBs) char 'A'

> 'A'.unpack('B4')
 => ["0100"]

он возвращает 4 MSBs char 'A'

> 'A'.unpack('B16')
 => ["01000001"]

он возвращает 16 MSBs char 'A', но так как есть только 8, мы получаем 8 MSBs

> 'AB'.unpack('B16')
 => ["0100000101000010"]

он возвращает 16 MSBs последовательности символов 'AB' (конец 8 бит 01000010 соответствует 'B')

> 'AB'.unpack('B10')
 => ["0100000101"]

он возвращает 10 MSBs последовательности символов 'AB', т. е. 8 MSBs 'A' и 2 MSBs 'B'

> 'ABC'.unpack('B*')
 => ["010000010100001001000011"]

он возвращает все MSBs последовательности символов 'ABC', (конец 8 бит 01000011 соответствует 'C')

> 'AB'.unpack('B8B8')
 => ["01000001", "01000010"]

возвращает следующий массив:

  • первым элементом является 8 MSBs char 'A'
  • второй элемент 8 MSBs чар 'B'

_

> 'AB'.unpack('B8B7')
 => ["01000001", "0100001"]

возвращает следующий массив:

  • первым элементом является 8 MSBs char 'A'
  • второй элемент-это 7 MSBs символа 'B'

_

> 'AB'.unpack('B4B8')
 => ["0100", "01000010"]

возвращает следующий массив:

  • первым элементом является 4 MSBs char 'A'
  • второй элемент 8 MSBs чар 'B'

_

> 'AB'.unpack('B16B8')
 => ["0100000101000010", ""]

возвращает следующий массив:

  • первым элементом является 16 MSBs последовательности символов 'AB'
  • второй элемент пуст, так как символы уже были потреблены

_

> 'AB'.unpack('B*B8')
 => ["0100000101000010", ""]

он дает вам тот же результат и потребляет всю строку.

> 'AB'.unpack('B9B8')
 => ["010000010", ""]

он возвращает следующее массив:

  • первым элементом является 9 MSBs последовательности символов 'AB'
  • второй элемент пуст, так как символы уже были потреблены

в заключение

директива BN над строкой будет потреблять не более первого ((N-1) / 8) + 1 символы строки. Если в строке все еще есть символы, и у вас есть вторая директива BM, вы будете потреблять не более следующего ((M-1) / 8) + 1 символы строки. И так далее для всех следующих директив. Если вы используете директиву B*, он будет потреблять все символы и возвращает последовательность их соответствующих MSBs.

например:

'ABCDEFG'.unpack('B17B*B8')

он должен вернуть нам:

  • 17 MSBs последовательности ABC
  • все MSBs последовательности DEFG
  • пустая битовая строка
давайте:
> 'ABCDEFG'.unpack('B17B*B8')
 => ["01000001010000100", "01000100010001010100011001000111", ""]

и действительно 'A'.unpack('B4B4') возвращает массив ["0100", ""] как первая директива потребляет char A.