为 32 位整数(只有 32 个条目)保留所有 2 的幂并不是什么大问题通过从较高和较低的数字中减去并获得abs。然后,您可以轻松决定添加哪个。
您可以通过获取您的数字的日志基数 2 并使用它来索引数组来避免搜索
更新:提醒此代码未经彻底测试。
#include <array>
#include <cmath>
#include <iostream>
const std::array<unsigned int,32> powers =
{
1,1<<1,1<<2,1<<3,1<<4,1<<5,1<<6,1<<7,1<<8,1<<9,1<<10,1<<11,1<<12,1<<13,1<<14,
1<<15,1<<16,1<<17,1<18,1<<19,1<<20,1<<21,1<<22,1<<23,1<<24,1<<25,1<<26,1<<27,
1<<28,1<<29,1<<30,1<<31 -1
};
std::array<unsigned int,32> powers_of_two() {
std::array<unsigned int,32> powers_of_two{};
for (unsigned int i = 0; i < 31; ++i) {
powers_of_two[i] = 1 << i;
}
powers_of_two[31]=~0;
return powers_of_two;
}
unsigned int round_to_closest(unsigned int number) {
if (number % 2 == 0) return number;
unsigned int i = std::ceil(std::log2(number));
//higher index
return (powers[i]-number) < (number - powers[i-1]) ?
++number:--number;
}
int main() {
std::cout << round_to_closest(27) << std::endl;
std::cout << round_to_closest(23) << std::endl;
return 0;
}
由于我不能代表 2 ^ 31 我使用了最接近它的无符号整数(全为 1),这意味着它们中的 1 个案例会产生不正确的结果,我认为这没什么大不了的。
我在想你可以使用 astd::vector<bool>
作为一个非常大的查找表来加 1 或减 1,这对我来说似乎有点过分了,因为这个操作似乎运行得很快。