Вы задаете вопрос об основных принципах хранения чисел в памяти компьютеров. Например, вы можете посмотреть на них, чтобы узнать больше:
http://en.wikipedia.org/wiki/Computer_number_format#Binary_Number_Representation
http://en.wikipedia.org/wiki/Signed_number_representations
В качестве примера возьмем разницу между S
и s
; оба используются для упаковки и распаковки 16-битных чисел, но один для целых чисел со знаком, а другой для беззнаковых. Это имеет важное значение, когда вы хотите распаковать строку обратно в исходные целые числа.
S
: 16-битные числа без знака означают числа от 0 до 65535 (от 0 до (2^16-1))
s
: 16-битные целые числа со знаком -32768 - 32767 (-(2^15) до (2^15) -1)) (один бит используется для знака)
Разницу можно увидеть здесь:
# S = unsigned: you cannot pack/unpack negative numbers
> [-1, 65535, 32767, 32768].pack('SSSS').unpack('SSSS')
=> [65535, 65535, 32767, 32768]
# s = signed: you cannot pack/unpack numbers outside range -32768 - 32767
> [-1, 65535, 32767, 32768].pack('ssss').unpack('ssss')
=> [-1, -1, 32767, -32768]
Итак, вы видите, что вам нужно знать, как числа представлены в памяти компьютера, чтобы понять ваш вопрос. Числа со знаком используют один бит для представления знака, в то время как числа без знака не нуждаются в этом дополнительном бите, но тогда вы не можете представлять отрицательные числа.
Это очень простой способ представления чисел в двоичном виде в памяти компьютера.
Причина, по которой вам нужна упаковка, например, заключается в том, что вам нужно отправить числа в виде потока байтов с одного компьютера на другой (например, по сетевому соединению). Вы должны упаковать свои целые числа в байты, чтобы их можно было отправить по потоку. Другой вариант — отправить числа в виде строк; затем вы кодируете и декодируете их как строки на обоих концах вместо упаковки и распаковки.
Или, допустим, вам нужно вызвать C-функцию в системной библиотеке из Ruby. Системные библиотеки, написанные на C, работают с основными целыми числами (int, uint, long, short и т. д.) и C-структурами (struct). Вам нужно будет преобразовать ваши целые числа Ruby в системные целые числа или C-структуры перед вызовом таких системных методов. В этих случаях pack
и unpack
можно использовать для взаимодействия с такими методами.
Что касается дополнительных директив, то они касаются порядка байтов представления упакованной последовательности байтов. Посмотрите здесь, что означает порядок следования байтов и как это работает:
http://en.wikipedia.org/wiki/Endianness
Проще говоря, он просто сообщает методу упаковки, в каком порядке целые числа должны быть преобразованы в байты:
# Big endian
> [34567].pack('S>').bytes.map(&:to_i)
=> [135, 7]
# 34567 = (135 * 2^8) + 7
# Little endian
> [34567].pack('S<').bytes.map(&:to_i)
=> [7, 135]
# 34567 = 7 + (135 * 2^8)
person
Casper
schedule
12.01.2013