这个怎么打印“你好世界”?

问题:

我发现这个奇怪:

for (long l = 4946144450195624l; l > 0; l >>= 5)
    System.out.print((char) (((l & 31 | 64) % 95) + 32));

输出:

hello world

这个怎么用?

回答:

数字4946144450195624适合64位,其二进制表示为:
class=”lang-none prettyprint-override”>

 10001100100100111110111111110111101100011000010101000

该程序从每个5位组解码一个字符,从右到左
class=”lang-none prettyprint-override”>

 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从组跳到组,则5位组在句子l & 31中将数字与掩码31₁₀ = 11111₂进行隔离,
现在代码将5位值映射到相应的7位ASCII字符。这是棘手的部分,检查小写的二进制表示
下表中的字母:
class=”lang-none prettyprint-override”>

  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 5位
9696₁₀ = 1100000₂)编纂,这应该足以做映射,但这对空间不起作用(darn space!)
现在我们知道必须特别注意与其他人物同时处理空间。为了达到这个目的,代码将打开第7位(但不是第6位)
提取的带有OR 64 64₁₀ = 1000000₂l & 31 | 64)的5位组。
到目前为止,5位组的格式为:10xxxxx₂(空格为1011111₂ = 95₁₀)。
如果我们可以将空间映射到不受其他值影响的0,那么我们可以把第6位打开,这应该是全部的。
这是mod 95部分来玩,空间是1011111₂ = 95₁₀,使用mod
操作(l & 31 | 64) % 95)只有空间可以追溯到0,之后,代码将第6位加入32₁₀ = 100000₂
对于先前的结果,((l & 31 | 64) % 95) + 32)将5位值转换为有效的ascii字符
class=”lang-none prettyprint-override”>

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位长的值:
class=”lang-java prettyprint-override”>
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); } } [/code]     Code问答: http://codewenda.com/topics/python/
Stackoverflow: How does this print “hello world”?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

20 − = 12