我发现了这种奇怪:
for (long l = 4946144450195624l; l > 0; l >>= 5)
System.out.print((char) (((l & 31 | 64) % 95) + 32));
输出:
hello world
这是如何运作的?
该数字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位,可以表示2 = 32个字符。英文字母包含26个字母,因此除字母外还留出32-26 =
6个符号的空间。通过这种编码方案,您可以拥有全部26个(一种情况)的英文字母和6个符号(其中是空格)。
该>>= 5
从组到组中的for循环跳跃,则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位编码,并且应该足以进行映射,但是这对于空间(无效空间!)不起作用
现在,我们知道必须特别注意与其他字符同时处理空间。为此,代码使用OR 64 64₁₀ = 1000000₂
(l & 31 | 64
)将提取的5位组的第7位(而不是第6位)打开。
到目前为止,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字符
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);
}
}
我从堆栈溢出的404 Not Found错误页面复制了下面的代码。 上面的代码编译精细,在控制台上打印404。我以为语句print(202*2);负责打印404,但我不对,因为更改此语句中的数字也打印404。 有人能帮我理解这个代码以及它是如何打印404的吗? 我发布编译输出供您参考,因为有评论说此代码无法编译。包含上述代码的文件是Test. c。 gcc测试。c-o测试 测验c: 3:1:警告:
问题内容: 搜索过,但没有找到满意的答案。 我知道没有可移植的方式来打印pthread_t。 您如何在您的应用程序中做到这一点? 更新: 实际上,我不需要pthread_t,但是需要一些小的数字ID,以便在调试消息中标识不同的线程。 在我的系统(64位RHEL 5.3)上,它被定义为unsigned long int,因此它的数量很大,仅打印它就在调试行中占据了宝贵的位置。 gdb 如何 分配 短
问题内容: 我正在为具有内置行式打印机的Android设备开发应用程序。我必须与此打印机进行交互,并使用它来打印收据上的详细信息,然后使用裁纸器自动剪切该收据。我已经在其中看到了一些ESC命令,但是我不知道如何执行这些ESC命令。 关于Casio设备打印机,我有三个主要问题: 1.我已经使用了内置打印机的打印代码,但是打印后切纸刀没有激活 2.我不知道如何在android中将ESC命令发送到打印机
问题内容: 我现在正在制作时钟,目前我的秒针,分针和时针都使用带有开始坐标和结束坐标的对象以图形方式绘制。 现在让我感到困惑的是如何使秒针每经过一秒就“滴答”。也就是说,如何更新坐标(由于开始坐标始终位于时钟的中心,因此我们不需要更新坐标),以使其顺时针移动6度?这使我感到困惑,因为单位圆的方向(以及弧度的方向)是逆时针方向。 问题答案: 这个例子]非常好用…
问题是,在这种代码状态下,文件和目录是这样打印的: 但是我需要先打开目录,然后打开文件:靠近。我试图找出问题出在哪里,但无济于事。我需要改变什么,在代码中的哪里得到想要的结果?
问题内容: 我有一个JSON文件,我想把它打印成一团糟。在Python中最简单的方法是什么? 我知道PrettyPrint带有一个“对象”,我认为它可以是一个文件,但是我不知道如何传递文件。仅使用文件名是行不通的。 问题答案: 该模块已经实现了一些基本的漂亮打印,其参数指定缩进多少空格: 要解析文件,请使用: