我的数字是二进制表示0000abcd
。
如何以最少的操作数将其转换为0a0b0c0d
?
如何将0a0b0c0d
转换回0000abcd
?
我在这里寻找解决方案: http://graphics.stanford.edu/~seander/bithacks.html和其他
一般来说问题比描述的要多一些。
第一个号码a₁b₁c₁d₁a₂b₂c₂d₂
和第二个号码a₃a₄b₃b₄c₃c₄d₃d₄
如果(a₁
和a₂
= 0
)则清除a₃
和a₄
,if {a₃
和{{1} } = a₄
)然后清除0
和a₁
等
我的解决方案:
a₂
更新:(感谢@AShelly)
a₁b₁c₁d₁a₂b₂c₂d₂
OR 0 0 0 0 a₁b₁c₁d₁ ( a₁b₁c₁d₁a₂b₂c₂d₂ >> 4)
----------------
0 0 0 0 a b c d
? (magic transformation)
? ? ? ? ? ? ? ?
----------------
0 a 0 b 0 c 0 d
OR a 0 b 0 c 0 d 0 (0 a 0 b 0 c 0 d << 1)
----------------
a a b b c c d d
AND a₃a₄b₃b₄c₃c₄d₃d₄
----------------
A₃A₄B₃B₄C₃C₄D₃D₄ (clear bits)
使用常量x = a₁b₁c₁d₁a₂b₂c₂d₂
x = (x | x >> 4) & 0x0F
x = (x | x << 2) & 0x33
x = (x | x << 1) & 0x55
x = (x | x << 1)
y = a₃a₄b₃b₄c₃c₄d₃d₄
y = (y | y >> 1) & 0x55
y = (y | y >> 1) & 0x33
y = (y | y >> 2) & 0x0F
y = (y | y << 4)
,0x0F0F0F0F
,0x33333333
(以及64位的两倍长)来处理32位。
答案 0 :(得分:2)
如果您正在寻找最少的操作,请使用查找表。
答案 1 :(得分:0)
你无法一次性完成,你应该逐位移位:
伪代码:
X1 = a₁b₁c₁d₁
X2 = a₂b₂c₂d₂
Bm = 1 0 0 0 // Bit mask
Result = 0;
while (/* some bytes left */)
{
Result += (X1 and Bm) << 1 or (X2 and Bm);
Bm = Bm shr 1
Result = Result shl 2;
}
结果你将获得a1a2b1b2c1c2d1d2
答案 2 :(得分:0)
我认为使用二进制算法和x86或x64处理器架构在较少的操作中不可能(没有查找表)。纠正我,如果我错了,但你的问题是移动位。拥有abcd
位,您希望在一次操作中获得0a0b0c0d
位。当你看到'a','b','c'和'd'必须经过多少位时,问题就出现了。
'a' was 4-th, became 7-th, distance travelled 3 bits
'b' was 3-rd, became 5-th, distance travelled 2 bits
'c' was 2-nd, became 3-rd, distance travelled 1 bit
'd' was 1-st, became 1-st, distance travelled 0 bits
没有这样的处理器指令会将这些位动态移动到不同的距离。虽然如果你有相同数字的不同输入表示是免费的,例如你已经预先计算了一个你在循环中使用的值,那么可能会获得一些优化,这就是你在使用其他知识时所获得的效果关于拓扑。您只需选择是否:
[4 cycles, n^0 memory]
[2 cycles, n^1 memory]
[1 cycle , n^2 memory]
答案 3 :(得分:0)
我有二进制数字 代表0000abcd。如何转换 它以0a0b0c0d为最小数量 操作
这不是“Interleave bits of X and Y",其中Y是0吗?Bit Twiddling Hacks Multiple Solutions不使用查找表。
如何将0a0b0c0d转换回0000abcd?