看看这些实现,我想知道是否可以解释具体操作背后的原因。不是来自计算机科学,我不确定为什么做出这些决定。
function binb2rstr(input) {
var str = []
for (var i = 0, n = input.length * 32; i < n; i += 8) {
var code = (input[i >> 5] >>> (24 - i % 32)) & 0xFF
var val = String.fromCharCode(code)
str.push(val)
}
return str.join('')
}
function rstr2binb(input) {
var output = Array(input.length >> 2)
for (var i = 0, n = output.length; i < n; i++) {
output[i] = 0
}
for (var i = 0, n = input.length * 8; i < n; i += 8) {
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32)
}
return output
}
到目前为止我所理解的是:
i += 8
用于迭代字节。0xFF
为255,即2^8 - 1
,因此为1个字节。|
是按位OR,<<
,>>>
和&
同样是位运算符。%
模数将值保持在x = x % max
的最大值。我不明白的是:
i >> 5
,如何选择。& 0xFF
,如何选择。24 - i % 32
,24来自。var code = (input[i >> 5] >>> (24 - i % 32)) & 0xFF
,如何从中计算字符代码。input.length >> 2
想知道这是否只是一个标准的计算机科学功能,因为很难分辨这些变量来自何处以及如何学习这些变量。看起来这些值必须是基于字节长度的标准算法,但我无法告诉如何使用这些开放式问题。谢谢你的帮助。
答案 0 :(得分:2)
这段代码包含一些非常聪明的基于32位值的比特 但是,让我们按照你的观点开展工作:
- i&gt;&gt; 5,如何选择。
醇>
这将i
除以32 ---对应于n = input.length * 32
总长度。考虑整个算法,这意味着在选择下一个(0,8,16,24)
值之前,会将一个值处理input
四次。
- &安培; 0xFF,如何选择。
醇>
这只是选择n位值的最低8位。
- 24 - i%32,其中24来自。
醇>
这与i += 8
有关。 i % 32
表示四个不同的迭代(32/8 = 4),即temp= (0, 8, 16, 24)
。因此24-temp
会产生(24,16,8,0)
。
- var code =(输入[i>&gt;&gt; 5]&gt;&gt;&gt;(24 - i%32))&amp; 0xFF,如何从中计算字符代码。
醇>
1. 1st iteration: i=0 ;24-0=24; input[0] >>> 24 & 0xFF = highest byte of input[0] shifted to lowest
2. 2nd iteration: i=8 ;24-8=16; input[0] >>> 16 & 0xFF = 2nd highest byte of input[0] shifted to 2nd lowest
3. 3rd iteration: i=16;24-16=8; input[0] >>> 8 & 0xFF = 2nd lowest byte of input[0] shifted to 2nd highest
4. 4th iteration: i=8 ;24-24=0; input[0] >>> 0 & 0xFF = lowest byte of input[0] shifted to highest
这是Big-Endian-Conversion
下一次迭代有i=32
并开始下一次迭代input[32/32]
= input[1]
。
总体而言,该算法将32位代码向右移动,并屏蔽最低的8位,以便String.fromCharCode(code)
用作CharCode。
最后一个是来自不同的算法,所以input.length >> 2
只需要division by 2
丢弃剩下的1个。
关于你的上一个问题:
似乎这些值必须是基于字节长度的标准算法,但我无法告诉如何使用这些开放式问题来实现这些目标。
这远非标准算法。它只是一个基于字节的聪明的位操作。
在汇编程序中,这段代码更容易理解
甚至有一条名为BSWAP
的指令在寄存器中的32位Big-Endian和Little-Endian值之间进行交换。