这是我的一般问题的后续行动: bit-twiddling-find-next-power-of-two
我现在创建了以下模板函数:
template <typename T>
T nextPowerOfTwo(T n)
{
std::size_t k=1;
n--;
do {
n |= n >> k ;
k <<=1;
}
while (k < sizeof(T)*8)
return ++n;
}
2个问题:
unsigned
中将T指定为nextPowerOfTwo(unsigned T n)
会引发编译错误。我可以以某种方式指定T是无符号的吗? 编辑:更正了代码,开头是垃圾
编辑:再次更正了代码。真的对不起。实际上很明显。但无论如何还要感谢提示。 我想删除它,但已经有太多的贡献了。
答案 0 :(得分:7)
如果你希望你的功能是通用的,你明确想要的,你也希望能够使用用户定义的类型,它不会有关键字unsigned
。相反,您应该使用std::numeric_limits
来测试签名(或者,在这种情况下,缺少签名)。
您也不应该使用8 * sizeof (T)
,而是使用numeric_limits
(再次)来确定您的类型有多少位。 : - )
答案 1 :(得分:4)
template <typename T>
T nextPowerOfTwo(T v)
{
if (v < 1) return 0;
--v;
for (int i = 0; i < sizeof v; ++i)
v |= v >> (1<<i);
return v + 1;
}
答案 2 :(得分:2)
template<typename T>
T nextPowerOfTwo(T n) {
--n;
for(T k=1;!(k&(1<<(sizeof(n)+1));k<<=1) n|=n>>k;
return ++n;
}
答案 3 :(得分:1)
要回答你的第一个问题,不,你不能。 T必须可以用完整的类型声明替换;在T之前放置unsigned会导致unsigned unsigned int或类似的东西。
这不完全是在幕后发生的事情,但它足以解释为什么你不能使用无符号。
答案 4 :(得分:1)
虽然@ hacker的版本在技术上是正确的,但我的Visual Studio 2008无法正确优化它。这是我的版本,完美无缺。它还根据您的请求仅执行对数数量的操作。尽管此版本不那么优雅,但Visual Studio实际上能够在不执行它的情况下计算nearestPowerOfTwo(value)
的值。 (当然,您必须启用优化)。
template <typename T, T v>
struct value_holder
{
static const T value = v;
};
template <typename T, typename value, typename partial_result>
struct ln_detail
{
typedef typename ln_detail<T, value_holder<T, (value::value >> 1)>, value_holder<T, partial_result::value + 1> >::type type;
};
template <typename T, typename partial_result>
struct ln_detail<T, value_holder<T, 1>, partial_result>
{
typedef partial_result type;
};
template <typename T, T value>
struct ln
{
static const T value = ln_detail<T, value_holder<T, value>, value_holder<T, 0> >::type::value;
};
template <typename T>
T nearestPowerOfTwo(T v)
{
if (v < 1) return 0;
--v;
for (int i = 0; i < ln<T, 8*sizeof v>::value; ++i)
v |= v >> (1<<i);
return v + 1;
}
答案 5 :(得分:0)
您可以通过更改循环测试来稍微改进一下,以检查数字是否小于2的幂:
template <typename T>
T nextPowerOfTwo(T n)
{
std::size_t k=1;
--n;
do {
n |= n >> k;
k <<= 1;
} while (n & (n + 1));
return n + 1;
}
算法现在是O(log2(n))而不是O(width_of_T_in_bits)。这应该对小n
有用,或者如果n
通常包含许多1位(尽管后者不会出现在改进的时间范围内)。
当然它可能实际上更慢,因为循环测试现在可能是2个CPU指令而不是你的单个指令。
编辑25/8/2009:感谢黑客注意到一个非常愚蠢的错误!现在修好了。