背景:给定一些输入字节 B0、B1、B2、B3 和 B4,我想从这 5 个字节中提取选定的位并生成一个输出字。
例如,将B i的第n位表示为,我希望能够写出一个映射f: (B0, B1, B2, B3, B4) → 。所以会回来。Bi[n]
B2[4] B3[5] B3[4] B3[3] B3[2] B3[1] B0[5] B0[3] B0[1]
f(0b11001, 0b01100, 0b10101, 0b10011, 0b11111)
0b010011101
C 中可能会执行此确切示例的表达式是
(B2 & 4 << 5) | (B3 << 3) | (B0 & 16 << 2) | (B0 & 4 << 1) | (B0 & 1)
使用简单的位掩码和位移。
问题:有什么方法可以简化这样的表达式以最小化需要执行的操作数量?
例如,我注意到 B3 被完整地复制到输出的某些位中,因此我将其放置在适当的位置,B3 << 3
而不是屏蔽和移动单个位。我首先想到的是卡诺图,因为它们在简化布尔表达式时派上用场,但我意识到,由于我在一个字节的不同部分提取和放置各个位,因此使用布尔代数不可能进行简化。
推理:我想这样做的原因是能够在 BBC micro:bit 上以程序员友好的方式点亮 LED。我希望 B0 到 B4 表示在物理 5x5 排列中打开了哪些 LED,但这些 LED 在电子上以复杂的 3x9 配置连接。有关 LED 的更多信息,请参见此处。
通常,模式会根据物理 3x9 排列存储在内存中,以便能够在单个指令中将此模式输出到 LED,但我希望能够以编程方式将 5x5 模式映射到 3x9 模式。然而,如上所示的表达式需要 5 次加载指令、9 次按位 AND/OR 运算和 4 次逻辑移位,这至少比普通方法的效率低 9 倍。