找到最重要位的算法

时间:2013-06-10 15:49:29

标签: algorithm search binary

嗨,谢谢你抽出时间回答我的问题。

我的一位朋友在接受采访时被问到以下问题:“给定一个二进制数字,找到最重要的位”。我立即想到了以下解决方案,但不确定它是否正确。

即,将字符串分成两部分并将两部分转换为十进制。如果左子阵列为十进制0,则在右子阵列中执行二进制搜索,寻找1。

这是我的另一个问题。是最重要的位,二进制数中最左边的1?你能给我看一个例子,当一个0是最重要的一个例子和解释时。

编辑:

下面的答案中似乎有点混乱,所以我正在更新问题以使其更加精确。采访者说“你有一个网站,你收到数据,直到最重要的位表示停止传输数据”你会如何告诉程序停止数据传输“

7 个答案:

答案 0 :(得分:12)

您也可以使用位移。伪代码:

number = gets
bitpos = 0
while number != 0
  bitpos++             # increment the bit position
  number = number >> 1 # shift the whole thing to the right once
end
puts bitpos

如果数字为零,则bitpos为零。

答案 1 :(得分:7)

通过使用仅基于De Bruijn序列的相当熟知的方法,可以通过仅使用C样语言指令来找到单词中的最高有效位(即,使用向下舍入来计算log2)。例如,对于32位值

unsigned ulog2(uint32_t v)
{ /* Evaluates [log2 v] */
  static const unsigned MUL_DE_BRUIJN_BIT[] = 
  {
     0,  9,  1, 10, 13, 21,  2, 29, 11, 14, 16, 18, 22, 25,  3, 30,
     8, 12, 20, 28, 15, 17, 24,  7, 19, 27, 23,  6, 26,  5,  4, 31
  };

  v |= v >> 1;
  v |= v >> 2;
  v |= v >> 4;
  v |= v >> 8;
  v |= v >> 16;

  return MUL_DE_BRUIJN_BIT[(v * 0x07C4ACDDu) >> 27];
}

然而,在实践中,更简单的方法(如展开的二进制搜索)通常可以正常或更好地工作。

答案 2 :(得分:1)

这是一种方法(不一定是最有效的方法,尤其是如果你的平台有单指令解决方案来查找第一个或计数前导零或类似的东西),假设二进制补码有符号整数和一个32位整数宽度。

int mask = (int)(1U<<31); // signed integer with only bit 32 set
while (! n & mask)        // n is the int we're testing against
  mask >>= 1;             // take advantage of sign fill on right shift of negative number
mask = mask ^ (mask << 1) // isolate first bit that matched with n

如果你想要第一个的位位置,只需添加一个从31开始的整数计数器,并在每次循环迭代时递减。

这样做的一个缺点是如果n == 0,它是一个无限循环,所以事先测试为零。

答案 3 :(得分:1)

编辑过的问题确实非常不同,但不是很清楚。你是谁”?从网站上读取数据的程序的网站或程序员?如果你是网站,你可以通过发送一个值(但可能是一个字节,可能是什么?)来使程序停止,并设置最高位。只需OR或ADD即可。如果您是程序员,则测试您收到的值的最高位,并在设置时停止读取。对于无符号字节,您可以像

那样进行测试
bool stop = received_byte >= 128;
or
bool stop = received_byte & 128;

对于有符号字节,您可以使用

bool stop = received_byte < 0;
or
bool stop = received_byte & 128;

如果你没有读取字节,但是比如32位字,则128更改为(1 << 31)

答案 4 :(得分:0)

我认为这是一个棘手的问题。最重要的一点总是1 :-)。如果采访者喜欢横向思维,这个答案应该是胜利者!

答案 5 :(得分:0)

如果您对C / C ++解决方案感兴趣,可以查看书籍"Matters Computational" by Jörg Arndt,其中您可以在“1.6.1隔离最高版本并找到其索引”部分中定义这些函数:

static inline ulong highest_one_idx(ulong x)
// Return index of highest bit set.
// Return 0 if no bit is set.
{
#if defined  BITS_USE_ASM
    return  asm_bsr(x);
#else  // BITS_USE_ASM

#if  BITS_PER_LONG == 64
#define MU0 0x5555555555555555UL  // MU0 == ((-1UL)/3UL) == ...01010101_2
#define MU1 0x3333333333333333UL  // MU1 == ((-1UL)/5UL)   == ...00110011_2
#define MU2 0x0f0f0f0f0f0f0f0fUL  // MU2 == ((-1UL)/17UL)  == ...00001111_2
#define MU3 0x00ff00ff00ff00ffUL  // MU3 == ((-1UL)/257UL)  == (8 ones)
#define MU4 0x0000ffff0000ffffUL  // MU4 == ((-1UL)/65537UL) == (16 ones)
#define MU5 0x00000000ffffffffUL  // MU5 == ((-1UL)/4294967297UL) == (32 ones)
#else
#define MU0 0x55555555UL  // MU0 == ((-1UL)/3UL) == ...01010101_2
#define MU1 0x33333333UL  // MU1 == ((-1UL)/5UL)   == ...00110011_2
#define MU2 0x0f0f0f0fUL  // MU2 == ((-1UL)/17UL)  == ...00001111_2
#define MU3 0x00ff00ffUL  // MU3 == ((-1UL)/257UL)  == (8 ones)
#define MU4 0x0000ffffUL  // MU4 == ((-1UL)/65537UL) == (16 ones)
#endif

    ulong r = (ulong)ld_neq(x, x & MU0)
        + ((ulong)ld_neq(x, x & MU1) << 1)
        + ((ulong)ld_neq(x, x & MU2) << 2)
        + ((ulong)ld_neq(x, x & MU3) << 3)
        + ((ulong)ld_neq(x, x & MU4) << 4);
#if  BITS_PER_LONG > 32
    r += ((ulong)ld_neq(x, x & MU5) << 5);
#endif
    return r;

#undef MU0
#undef MU1
#undef MU2
#undef MU3
#undef MU4
#undef MU5
#endif
}

根据您的处理器架构实现asm_bsr

// i386
static inline ulong asm_bsr(ulong x)
// Bit Scan Reverse: return index of highest one.
{
    asm ("bsrl %0, %0" : "=r" (x) : "0" (x));
    return x;
}

// AMD64
static inline ulong asm_bsr(ulong x)
// Bit Scan Reverse
{
    asm ("bsrq %0, %0" : "=r" (x) : "0" (x));
    return x;
}

到这里查看代码:http://jjj.de/bitwizardry/bitwizardrypage.html

答案 6 :(得分:-1)

我不知道这太棘手了。)

我会将二进制数转换为dec然后我会直接返回数字的logaritm base 2(从float转换为int)。

解决方案是从右边开始的(返回的数字+ 1)位。

就我所知,最左边的1

给你答案