Rom*_*kin 1 ruby bit-manipulation
如何在Ruby中彼此清除字符串,然后将其转换为字节数组?我了解我需要对每个字节使用0x01010101值进行AND操作。但是困难在于如何正确地将字符串转换为二进制。理想情况下,它应该快速并且分配的数量最少。
稍后,我将需要将此值传递给Digest::MD5.hexdigest。
首先,请注意0x以16 0b为底数是2:
0b11111111.to_s(2) #=> "11111111"
0x11111111.to_s(2) #=> "10001000100010001000100010001"
Run Code Online (Sandbox Code Playgroud)
在转换字节内的位时,要0b...用于掩码。
下一个,
0b01010101.to_s(2) #=> "1010101"
Run Code Online (Sandbox Code Playgroud)
表明与所有整数一样,前导零被删除,这意味着您可以包含或不包含它们。考虑,
0b11111111 & 0 #=> 0
Run Code Online (Sandbox Code Playgroud)
可以看出,作为掩码,零被视为具有7个零的前导位。我们看到
(0b11111111 &
0b1010101).to_s(2) #=> "1010101"
Run Code Online (Sandbox Code Playgroud)
因此,我们可以将您的按位掩码定义为
MASK = 0b1010101
Run Code Online (Sandbox Code Playgroud)
现在,我们可以将String#unpack与格式字符串"C*"一起使用,以将字符串转换为8位无符号整数的数组,然后将其按位与MASK(使用&):
str = "Let's party, now!"
str.unpack("C*").map { |u| u & MASK }
#=> [68, 69, 84, 5, 81, 0, 80, 65, 80, 84, 81, 4, 0, 68, 69, 85, 1]
Run Code Online (Sandbox Code Playgroud)
的"C"在"C*"装置中的格式指令"C"被施加到第一个字符; "*"表示"C"对所有后续字符重复。
另请参阅Integer#&。
我从@DavidKling的答案中看到,有人可以选择写
str.bytes.map { |u| u & MASK }
Run Code Online (Sandbox Code Playgroud)