How does this print “hello world”?
我发现了这个奇怪的地方:
1 2 | for (long l = 4946144450195624l; l > 0; l >>= 5) System.out.print((char) (((l & 31 | 64) % 95) + 32)); |
输出:
1 | hello world |
这是怎么工作的?
数字
1 | 10001100100100111110111111110111101100011000010101000 |
程序从右到左为每5位组解码一个字符。
1 2 | 00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000 d | l | r | o | w | | o | l | l | e | h |
5位编码
对于5位,可以表示2?=32个字符。英文字母表包含26个字母,这为32-26=6个符号留出了空间除了字母。有了这个编码方案,您可以拥有所有26(一个案例)的英文字母和6个符号(其中的空格)。
算法描述for循环中的
现在,代码将5位值映射到相应的7位ASCII字符。这是一个棘手的部分,检查小写字母的二进制表示。下表中的字母:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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位集(
现在我们知道,在处理空间的同时,必须特别注意其他角色。为此,代码打开第7位(但不是第6位)。提取的具有或64个
到目前为止,5位组的形式是:
1 2 3 4 5 6 7 | 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位长值:
1 2 3 4 5 6 7 8 9 10 11 12 |
为上述答案增加一些价值。下面的groovy脚本打印中间值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | String getBits(long l) { return Long.toBinaryString(l).padLeft(8,'0'); } for (long l = 4946144450195624l; l > 0; l >>= 5){ println '' print String.valueOf(l).toString().padLeft(16,'0') print '|'+ getBits((l & 31 )) print '|'+ getBits(((l & 31 | 64))) print '|'+ getBits(((l & 31 | 64) % 95)) print '|'+ getBits(((l & 31 | 64) % 95 + 32)) print '|'; System.out.print((char) (((l & 31 | 64) % 95) + 32)); } |
这里是
1 2 3 4 5 6 7 8 9 10 11 | 4946144450195624|00001000|01001000|01001000|01101000|h 0154567014068613|00000101|01000101|01000101|01100101|e 0004830219189644|00001100|01001100|01001100|01101100|l 0000150944349676|00001100|01001100|01001100|01101100|l 0000004717010927|00001111|01001111|01001111|01101111|o 0000000147406591|00011111|01011111|00000000|00100000| 0000000004606455|00010111|01010111|01010111|01110111|w 0000000000143951|00001111|01001111|01001111|01101111|o 0000000000004498|00010010|01010010|01010010|01110010|r 0000000000000140|00001100|01001100|01001100|01101100|l 0000000000000004|00000100|01000100|01000100|01100100|d |
很有趣!
可见的标准ASCII字符在32到127之间。
这就是为什么你看到32和95(127-32)。
实际上,每个字符都映射到这里的5位(您可以找到每个字符的5位组合),然后将所有的位连接起来形成一个大数字。
正长整型是63位数字,大到足以容纳12个字符的加密形式。所以它足够大,可以容纳
在一个应用程序中,我们希望通过短信传输可见的英语字符、波斯语字符和符号。如您所见,可能有
我们将每个UTF-8(16位)字符转换为7位,并获得超过56%的压缩比。所以我们可以用同样数量的短信发送两倍长度的短信。(不知怎么地,这里也发生了同样的事情)。
您得到的结果恰好是下面值的
1 2 3 4 5 6 7 8 9 10 11 | 104 -> h 101 -> e 108 -> l 108 -> l 111 -> o 32 -> (space) 119 -> w 111 -> o 114 -> r 108 -> l 100 -> d |
您已经将字符编码为5位值,并将其中11个字符压缩为64位长。
正如你所说,最困难的部分是编码空间。小写英文字母在Unicode(和ASCII,以及大多数其他编码)中占据连续范围97-122,但空格为32。
为了克服这个问题,你用了一些算术。
它打印"Hello World"的原因与此类似:
1 2 |
但原因与此稍有不同:
1 2 |
不安
在mostly与
简单的convert
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | SQL> CREATE OR REPLACE FUNCTION dec2bin (N in number) RETURN varchar2 IS 2 binval varchar2(64); 3 N2 number := N; 4 BEGIN 5 while ( N2 > 0 ) loop 6 binval := mod(N2, 2) || binval; 7 N2 := trunc( N2 / 2 ); 8 end loop; 9 return binval; 10 END dec2bin; 11 / Function created. SQL> show errors No errors. SQL> |
易于使用的功能是把两个二元价值
1 2 3 4 5 6 7 | SQL> SELECT dec2bin(4946144450195624) FROM dual; DEC2BIN(4946144450195624) -------------------------------------------------------------------------------- 10001100100100111110111111110111101100011000010101000 SQL> |
现在我明白是
1 | 100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000 |
我们会离开我终于与他三位国际比权。因为,我们的仇恨总53位的二进制转换。
1 2 3 4 5 6 7 | SQL> SELECT LENGTH(dec2bin(4946144450195624)) FROM dual; LENGTH(DEC2BIN(4946144450195624)) --------------------------------- 53 SQL> |
所以,现在我们有:
1 | 00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000 |
现在,我们需要它convert 7位ASCII值。的特点是简单的,我们需要看到的是第六和第七位。添加两个
这是给予:
1 | 1100100|1101100|1110010|1101111|1110111|1111111|1101111|1101100|1101100|1100101|1101000 |
简单的interpret的二进制值,将使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | SQL> CREATE OR REPLACE FUNCTION bin2dec (binval in char) RETURN number IS 2 i number; 3 digits number; 4 result number := 0; 5 current_digit char(1); 6 current_digit_dec number; 7 BEGIN 8 digits := length(binval); 9 for i in 1..digits loop 10 current_digit := SUBSTR(binval, i, 1); 11 current_digit_dec := to_number(current_digit); 12 result := (result * 2) + current_digit_dec; 13 end loop; 14 return result; 15 END bin2dec; 16 / Function created. SQL> show errors; No errors. SQL> |
简单的面貌,每个二元价值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | SQL> set linesize 1000 SQL> SQL> SELECT bin2dec('1100100') val, 2 bin2dec('1101100') val, 3 bin2dec('1110010') val, 4 bin2dec('1101111') val, 5 bin2dec('1110111') val, 6 bin2dec('1111111') val, 7 bin2dec('1101111') val, 8 bin2dec('1101100') val, 9 bin2dec('1101100') val, 10 bin2dec('1100101') val, 11 bin2dec('1101000') val 12 FROM dual; VAL VAL VAL VAL VAL VAL VAL VAL VAL VAL VAL ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- 100 108 114 111 119 127 111 108 108 101 104 SQL> |
简单的看他们是什么人物。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | SQL> SELECT chr(bin2dec('1100100')) character, 2 chr(bin2dec('1101100')) character, 3 chr(bin2dec('1110010')) character, 4 chr(bin2dec('1101111')) character, 5 chr(bin2dec('1110111')) character, 6 chr(bin2dec('1111111')) character, 7 chr(bin2dec('1101111')) character, 8 chr(bin2dec('1101100')) character, 9 chr(bin2dec('1101100')) character, 10 chr(bin2dec('1100101')) character, 11 chr(bin2dec('1101000')) character 12 FROM dual; CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER --------- --------- --------- --------- --------- --------- --------- --------- --------- --------- --------- d l r o w ? o l l e h SQL> |
所以,我们怎么得到的输出?
D L r o w?O L E H
这是凯蒂吗?世界在反转。唯一的问题是空间。冰阱和合理的城市"explained higuaro在他的回答。在honestly不能interpret空间形式公布自己的第一届广交会上,直到在他的《解释给定的答案。
我发现斯莱特利的代码更容易吗?当被理解为PHP作为follows:
1 2 3 4 5 6 7 8 | <?php $result=0; $bignum = 4946144450195624; for (; $bignum > 0; $bignum >>= 5){ $result = (( $bignum & 31 | 64) % 95) + 32; echo chr($result); } |
看到活着的代码
out.println((char)(((L &;31 | 64)95 %)* + 32 1002439 1002439));
使它灯头:3