Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在O(log2(amount_bits))中使用二进制搜索查找下限(log2(int))时遇到问题_C++_Algorithm_Binary - Fatal编程技术网

C++ 在O(log2(amount_bits))中使用二进制搜索查找下限(log2(int))时遇到问题

C++ 在O(log2(amount_bits))中使用二进制搜索查找下限(log2(int))时遇到问题,c++,algorithm,binary,C++,Algorithm,Binary,在我们的算法课上,教授在实验课上提出了一个额外的问题。在log2(n)步中查找n位整数的下限(log2(x))(例如,当T=uint64\u T时,则n=64) 我们已经发现,我们应该能够用二进制搜索来解决这个问题,但在某些边缘情况下,我们会得到一个1比1的结果或一个无休止的循环。我们挠头已经有一段时间了,但似乎无法正确处理。我们如何最好地处理这个问题?我们已经试着用讨论过的不变技巧进行推理,但它似乎比我们想象的要复杂一些。例如,对于十进制数,在第7位或第6位之间进行选择很困难,因为128大于1

在我们的算法课上,教授在实验课上提出了一个额外的问题。在log2(n)步中查找n位整数的下限(log2(x))(例如,当T=uint64\u T时,则n=64)

我们已经发现,我们应该能够用二进制搜索来解决这个问题,但在某些边缘情况下,我们会得到一个1比1的结果或一个无休止的循环。我们挠头已经有一段时间了,但似乎无法正确处理。我们如何最好地处理这个问题?我们已经试着用讨论过的不变技巧进行推理,但它似乎比我们想象的要复杂一些。例如,对于十进制数,在第7位或第6位之间进行选择很困难,因为128大于100,但64小于100。不幸的是,在缓解这种情况时,我们打破了一些边缘案例

编辑:如下所述,这纯粹是一个学术问题,在现实场景中可用性很低甚至没有

以下是我们目前的代码:

//
//   h      l
//   76543210
// 0b01000001 = 65
//

using T = unsigned char;

int lgfloor(T value)
{
    assert(value > 0);

    int high = ((sizeof(value) * 8) - 1);
    int low = 0;
    int mid = 0;
    T guess = 0;

    while (high > low)
    {
        mid = (low + ((high - low) / 2));
        guess = static_cast<T>(1) << mid;

        printf("high: %d, mid: %d, low: %d\n", high, mid, low);

        if (value < guess)
        {
            high = mid - 1;
        }
        else
        {
            low = mid;
        }
    }

    return low;
}
提前感谢,, 致以亲切的问候


Marten

无休止的循环是由这条线造成的:

 mid = (low + ((high - low) / 2));

如果
high
low
相差1,则结果可能是
mid==low
,然后在while循环中导致
low=mid
的条件下,您将永远检查相同的条件。我的建议是,如果循环中有
low=mid
,则必须确保
mid!=在这种情况下为低
。因此,只需在分配之前检查此项,如果出现这种情况,请执行
low=mid+1

您需要一个适当的退出条件。比如说
y=floor(lg2(x))
。当
2^low似乎只需将if移到正确的“log”时间,直到出现“1”时,您应该退出循环

using T = unsigned char;

int lgfloor(T value)
{
  assert(value > 0);

  int log = 0;
  while(value != 1) {
    value >> 1;
    log++;
  }
  return log;
}

必须在
lg(n)
步骤中找到解决方案,这意味着像
low=0
high=32
这样的初始化将不起作用,因为它在每种情况下都需要
5
步骤,并且在
x
大于
2^32
的情况下不起作用。正确的解决方案必须结合第一次几何搜索(指数加倍),然后是标准的二分法搜索

# Geometric search
low= 0
high= 1
while (1 << high) <= x:
    low= high
    high+= high

# Dichotomic search
while high - low > 1:
    mid= (high + low) >> 1
    if x < mid:
        high= mid
    else:
        low= mid
#几何搜索
低=0
高=1
而(1>1
如果x
在您的平台上是
char
有符号还是无符号?如果是无符号的,您的断言会很有趣。由于建议只对无符号量执行移位,但您需要使用有符号输入进行测试,因此您需要确定要使用哪一个。@Max Langhof该算法对于使用T=unsigned long long int
,这是我们最初开发此方法时使用的类型。我只是想帮助您改进此问题。我知道这些挑剔不是您主要关心的问题,但当您不关心这些问题时,其他人被困在这些问题上会很恼火。在任何情况下,您发现了什么调试时?哪个测试用例失败,您的搜索采取了哪些步骤?
if(value
导致lgfloor(1)失败。
if(value
导致lgfloor(2)中的无休止循环:
high:2,mid:1,low:1
。修复一个案例会导致其他案例失败。我们怀疑这不是一般的二进制搜索应用程序,但有一个我们经常忽略的额外困难。我们调试了此方法的各种变体,但似乎总是在一个或另一个测试中失败。@MartenBE在这种情况下,只需添加一个检查f或者
guess==value
并返回
mid
。请注意
low
在您的实现中永远无法达到
high
,因此如果在任何时候
high
是正确的猜测,那么您当前无法返回
high
(您只返回
low
)。或者,你试过
high=mid
low=mid
吗?同样,如果你坐下来拿一张纸,用手做一次,正确的解决方案应该非常明显(我承认我自己没有做过)。我们试过,但这样的解决方案失败了(100):
if(value==guess){return mid;}else if(value
。另外:
如果(value
也给出了一个无休止的循环:
高:7,中:6,低:6
。这真的很棘手:pOk
value==guess
当然是错误的。你需要检查的是你是否在最左边。也就是说,
如果((guess^value)
。还请注意,有一个内在因素可以为您完成整个作业说明(本质上是O(1)):。不符合分配条件(我的意思是,您可以争辩说,加法、除法移位和比较的内置操作都是O(numBits)完全相同),但万一你在实践中不得不这样做,你知道。这个解决方案是O(amount\u bits),而不是O(log2(amount\u bits))。
if (value < guess)
  high = mid;
else
  low = mid;
int lgfloor(T value)
{
    assert(value > 0);

    int high = (sizeof(value) * 8);
    int low = 0;

    while (high > low+1)
    {
        int mid = (low + ((high - low) / 2));
        T guess = static_cast<T>(1) << mid;

        printf("high: %d, mid: %d, low: %d\n", high, mid, low);

        if (value < guess)
            high = mid;
        else
            low = mid;
    }

    return low;
}
using T = unsigned char;

int lgfloor(T value)
{
  assert(value > 0);

  int log = 0;
  while(value != 1) {
    value >> 1;
    log++;
  }
  return log;
}
# Geometric search
low= 0
high= 1
while (1 << high) <= x:
    low= high
    high+= high

# Dichotomic search
while high - low > 1:
    mid= (high + low) >> 1
    if x < mid:
        high= mid
    else:
        low= mid