数字4946144450195624适合64位,其二进制表示为:
10001100100100111110111111110111101100011000010101000
该程序对每5位组的字符进行解码,从右到左
00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000
d | l | r | o | w | | o | l | l | e | h
5位编码
对于5位,可以表示2 5 = 32个字符。英语字母表包含26个字母,这为32 – 26 = 6个符号留出空间
除了字母。使用这种编码方案,您可以拥有所有26(一个案例)英文字母和6个符号(它们之间的空格)。
算法描述
在for-loop从组跳到组的情况下,5位组被隔离,并且该数字与语句l& l中的掩码3110 = 11111 2相乘。 31
现在代码将5位值映射到其对应的7位ascii字符。这是棘手的部分,检查小写的二进制表示
字母表中的字母:
ascii | ascii | ascii | algorithm
character | decimal value | binary value | 5-bit codification
--------------------------------------------------------------
space | 32 | 0100000 | 11111
a | 97 | 1100001 | 00001
b | 98 | 1100010 | 00010
c | 99 | 1100011 | 00011
d | 100 | 1100100 | 00100
e | 101 | 1100101 | 00101
f | 102 | 1100110 | 00110
g | 103 | 1100111 | 00111
h | 104 | 1101000 | 01000
i | 105 | 1101001 | 01001
j | 106 | 1101010 | 01010
k | 107 | 1101011 | 01011
l | 108 | 1101100 | 01100
m | 109 | 1101101 | 01101
n | 110 | 1101110 | 01110
o | 111 | 1101111 | 01111
p | 112 | 1110000 | 10000
q | 113 | 1110001 | 10001
r | 114 | 1110010 | 10010
s | 115 | 1110011 | 10011
t | 116 | 1110100 | 10100
u | 117 | 1110101 | 10101
v | 118 | 1110110 | 10110
w | 119 | 1110111 | 10111
x | 120 | 1111000 | 11000
y | 121 | 1111001 | 11001
z | 122 | 1111010 | 11010
在这里你可以看到我们想要映射的ASCII字符从第7和第6位(11xxxxx2)开始(除了空格,只有第6位),你可以或5位
编码96(9610 = 11000002),这应该足以做映射,但这不会为空间工作(darn空间!)
现在我们知道必须特别小心处理空间与其他字符同时。为此,代码将第7位(但不是第6位)置1
提取的5位组具有OR 64 64 10 = 1000000 2(1& 31 | 64)。
到目前为止,5位组的形式是:10xxxxx 2(空间将是1011111 2 = 9510)。
如果我们可以将空间映射为0而不影响其他值,那么我们可以打开第6位,应该全部。
这里是mod 95部分来演奏,空间是1011111 2 = 95 10,使用mod
操作(1& 31 | 64)%95)只有空间返回到0,此后,代码通过加上3210 = 100000 2打开第6位
((1& 31 | 64)%95)32)将5位值转换为有效的ASCII字符
isolates 5 bits --+ +---- takes 'space' (and only 'space') back to 0
| |
v v
(l & 31 | 64) % 95) + 32
^ ^
turns the | |
7th bit on ------+ +--- turns the 6th bit on
以下代码执行逆过程,给定一个小写字符串(最多12个字符),返回64位长的值,可以与OP的代码一起使用:
public class D {
public static void main(String... args) {
String v = "hello test";
int len = Math.min(12, v.length());
long res = 0L;
for (int i = 0; i < len; i++) {
long c = (long) v.charAt(i) & 31;
res |= ((((31 - c) / 31) * 31) | c) << 5 * i;
}
System.out.println(res);
}
}