【发布时间】:2019-08-18 01:40:42
【问题描述】:
在我们的算法课上,教授在实验课上多了一道题。在 log2(n) 步中找到 n 位 int 的 floor(log2(x))(例如,当 T = uint64_t 时,n = 64)。
我们发现我们应该能够通过二分搜索来解决这个问题,但是在某些边缘情况下我们会得到一个关闭 1 的结果或无限循环。我们摸索了一段时间,但似乎无法做到这一点。我们如何最好地处理这个问题?我们试图用here 讨论的不变技巧来推理,但它似乎比它复杂一点。例如。对于十进制数,在第 7 位或第 6 位之间进行选择很困难,因为 128 大于 100,但 64 更小。不幸的是,在缓解这个问题时,我们打破了一些极端情况。
编辑:如下所述,这纯粹是一个学术问题,在现实生活中几乎没有可用性。
到目前为止,这是我们的代码:
//
// 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;
}
我们创建了以下单元测试(使用 GoogleTest):
TEST(LgFloor, lgfloor)
{
ASSERT_DEATH(lgfloor(-1), "Assertion `value > 0' failed.");
ASSERT_DEATH(lgfloor(0), "Assertion `value > 0' failed.");
ASSERT_EQ(lgfloor(1), 0);
ASSERT_EQ(lgfloor(2), 1);
ASSERT_EQ(lgfloor(64), 6);
ASSERT_EQ(lgfloor(100), 6);
}
提前致谢, 亲切的问候,
貂
【问题讨论】:
-
char在您的平台上是否已签名或未签名?如果它没有签名,那么你的断言会很有趣。由于建议仅对无符号数量执行移位,但您希望使用有符号输入进行测试,因此您需要确定要使用哪一个。 -
@Max Langhof 对于
using T = unsigned long long int,该算法同样失败,这是我们最初开发此方法时使用的类型。 -
我只是想帮助您改进问题。我知道这些挑剔不是您的主要关注点,但是当这些问题不是您关心的问题时,其他人会被困在这些问题上,这很烦人。
-
无论如何,你在调试这个的时候发现了什么? 哪个测试用例失败了,您的搜索采取了哪些步骤?