[英]Looking for a more efficient bitfield decode algorithm
我有一个Visual Studio 2008 C ++应用程序,我收到一个位图(不是图像)。 翻转的每个位对应于解码图上的位置。
typedef unsigned char BYTE;
const unsigned int COL_COUNT = 8;
const unsigned int ROW_COUNT = 4;
static char g_decode_map[ ROW_COUNT ][ COL_COUNT ] =
{
{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' },
{ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p' },
{ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x' },
{ 'y', 'z', ',', '.', ' ', ':', '-', '+' }
};
// current implementation
void Decode( const BYTE bitmap[ ROW_COUNT ],
const char decode_map[ ROW_COUNT ][ COL_COUNT ],
char decoded[ ROW_COUNT * COL_COUNT ] )
{
int found = 0;
for( int i = 0; i < ROW_COUNT; ++i )
{
for( int j = 0; j < COL_COUNT; ++j )
{
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( j ) )
{
decoded[ found++ ] = g_decode_map[ i ][ COL_COUNT - j - 1 ];
}
}
}
}
int main( int argc, char* argv[] )
{
BYTE bitmap[ ROW_COUNT ] = { 0x01, 0x80, 0x00, 0x00 };
// expected output { 'h', 'i' } or { 'i', 'h' } order is unimportant
char decoded[ ROW_COUNT * COL_COUNT + 1 ] = { };
Decode( bitmap, g_decode_map, decoded );
printf( "Decoded: %s\r\n", decoded );
return 0;
}
我当前的解码实现工作正常,但我觉得可能有一种更有效的方法。 任何人都可以建议一个更高性能的算法吗?
测试每个位是否通过按位运算设置会更快,而不是为每个被测试的位创建位集。 尝试这样的事情:
for( int i = 0; i < ROW_COUNT; ++i ) {
for( int j = 0; j < COL_COUNT; ++j ) {
if(bitmap[i] & (1 << j)) {
...
1 << j
生成一个只有你想要测试的位的掩码。 只有在bitmap[i]
设置该bitmap[i]
时,使用位图字节对掩码进行按位和返回才会返回true。 这个条件的结果应该等同于条件的结果,它应该快得多。
你正在进行64次条件检查。 for循环中为32,for循环中为32。 如果你无法摆脱for循环中的32,你可以做的最好是循环展开以减少forloops正在执行的条件语句的数量。 将行和列长度定义为常量。 您可以展开循环并对索引的一些数字进行硬编码。 您可以编写8个if语句,而不是内部for循环。
这就留下了一个问题,如果有人改变常数值怎么办? 然后代码中断了。 那是对的。 如果你需要它足够强大以抵御它,你可以使用编译时递归来展开循环(下面的链接)。 此外,任何看过你的代码的人都会在恐惧中畏缩,并认为你是一个上帝。 :P另外,杰森的解决方案也会加快速度。
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 0 ) )
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 1 ) )
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 2 ) )
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 3 ) )
...
if( std::bitset< COL_COUNT >( bitmap[ i ] ).test( 7 ) )
这是如何快速完成的,假设COL_COUNT == 8
(要做得非常快,请使用COL_COUNT == 8
汇编程序):
for( int i = 0; i < ROW_COUNT; ++i )
{
unsigned char next_byte = bitmap[i] ;
for( int j = 0; j < COL_COUNT; ++j )
{
if (next_byte & 0x80)
{
decoded[ found++ ] = g_decode_map[ i ][ j ];
}
next_byte <<= 1 ;
}
}
我已将其编码为重现您程序的行为 - 但您确定自己拥有它吗? 我希望你递增found
每一次,不只是当一个1
位被发现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.