我发现了这种奇怪:
for (long l = 4946144450195624l; l > 0; l >>= 5) System.out.print((char) (((l & 31 | 64) % 95) + 32));
输出:
hello world
这是如何运作的?
该数字4946144450195624适合64位,其二进制表示为:
4946144450195624
10001100100100111110111111110111101100011000010101000
程序从右到左为每个5位组解码一个字符
00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000 d | l | r | o | w | | o | l | l | e | h
对于5位,可以表示2 = 32个字符。英文字母包含26个字母,因此除字母外还留出32-26 = 6个符号的空间。通过这种编码方案,您可以拥有全部26个(一种情况)的英文字母和6个符号(其中是空格)。
该>>= 5从组到组中的for循环跳跃,则5位组被分离安定与掩模的数目31₁₀ = 11111₂在句子l & 31
>>= 5
31₁₀ = 11111₂
l & 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位设置(11xxxxx₂)开头(空格除外,该位置只有第6位),可以OR使用96(96₁₀ = 1100000₂)进行5位编码,并且应该足以进行映射,但是这对于空间(无效空间!)不起作用
11xxxxx₂
OR
96
96₁₀ = 1100000₂
现在,我们知道必须特别注意与其他字符同时处理空间。为此,代码使用OR 64 64₁₀ = 1000000₂(l & 31 | 64)将提取的5位组的第7位(而不是第6位)打开。
64₁₀ = 1000000₂
l & 31 | 64
到目前为止,5位组的形式为:(10xxxxx₂空格为1011111₂ = 95₁₀)。如果我们可以将空间映射为不0影响其他值,则可以打开第6位,仅此而已。这是mod 95要发挥作用的部分,空格是1011111₂ = 95₁₀,使用mod操作,(l & 31 | 64) % 95)只有空格返回到0,然后,代码通过将32₁₀ = 100000₂ 前一个结果加到第6位,((l & 31 | 64) % 95) + 32)将5位值转换为有效的ascii字符
10xxxxx₂
1011111₂ = 95₁₀
0
mod 95
(l & 31 | 64) % 95)
32₁₀ = 100000₂
((l & 31 | 64) % 95) + 32)
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个字符)的情况下,以下代码执行相反的过程,返回可与OP的代码一起使用的64位长的值:
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); } }