C++ 将设置位移到64位整数的末尾

C++ 将设置位移到64位整数的末尾,c++,algorithm,bit-manipulation,C++,Algorithm,Bit Manipulation,我正在处理一个函数,该函数以一个64位整数作为参数,并返回一个64位整数,最后包含所有设置位 01011001 -> 00001111 // examples 00010100 -> 00000011 我首先想到了以下算法: nb_ones = countSetBit(x) int64 res = 1 for i from 1 to nb_ones+1: res |= (1 << i) nb_one=countSetBit(x) int64 res=1 对

我正在处理一个函数,该函数以一个64位整数作为参数,并返回一个64位整数,最后包含所有设置位

01011001 -> 00001111   // examples
00010100 -> 00000011
我首先想到了以下算法:

nb_ones = countSetBit(x)
int64 res = 1
for i from 1 to nb_ones+1:
    res |= (1 << i)
nb_one=countSetBit(x)
int64 res=1
对于从1到nb_ones+1的i:

res |=(1countSetBit)它可能已经针对您的平台进行了优化

要在末尾设置给定数量的1,只需转到2的下一次幂并减去1即可

nb_ones = countSetBit(x)
int64 res = nb_ones == 64 ? -1 : ((1 << nb_ones) - 1);
nb_one=countSetBit(x)

int64 res=nb_ones==64?-1:((1您可以避免循环:

const auto nb_ones = countSetBit(x)
if (nb_ones == 64) {
    return -1; // 0xFFFFFFFFFFFFFFFF;
} else {
    return (1u << nb_ones) - 1;
}
const auto nb\u ones=countSetBit(x)
如果(注意=64){
return-1;//0xffffffffffffff;
}否则{

返回(1u我认为您只需一个循环即可:

std::uint64_t bits_to_end(std::uint64_t n)
{
    std::uint64_t x = 0;

    for(std::uint64_t bit = 0, pos = 0; bit < 64; ++bit)
        if(n & (1ULL << bit))
            x |= (1ULL << pos++);

    return x;
}
std::uint64位到端(std::uint64\u n)
{
标准:uint64_t x=0;
用于(std::uint64_t位=0,位=0;位<64;++位)

if(n&(1ULL计数所有位有点过分,因为大多数CPU都有一个针对零的有效测试

因此,我们要做的是将其作为退出条件:

output = 0;
while (input != 0) {
  if (input & 1) output = (output<<1)+1;
  input >>= 1;
}
输出=0;
while(输入!=0){
如果(输入和1)输出=(输出=1;
}
循环将输入向右移位,每当一位从
输入
移位时,向
输出
添加一个额外的位。显然,这会向
输出
添加与
输入
中相同的位(可能为0,可能为64)。但是,
输出
中的位是连续的,因为只有在添加位时,
输出
才会移位

如果你的CPU有一个位计数操作,那当然会更快。如果你在x86或ARM汇编中实现这一点,你会使用这样一个事实:
input&1
是由
>=1

移出的同一位,因为你有几个有效的答案,当你实际要求一个简单的答案时,你会得到一个缓慢但-c>的答案从概念上讲,对多样性的回答非常简单:

uint64_t num(uint64_t x)
{
    // construct a base-2 string
    auto s = std::bitset<64>(x).to_string();
    // sort the 1s to the end
    std::sort(begin(s), end(s));
    // and convert it back to an integer
    return std::bitset<64>(s).to_ulong();
}
uint64\u t num(uint64\u t x)
{
//构造一个base-2字符串
自动s=std::位集(x).to_string();
//将1排序到最后
排序(开始、结束);
//并将其转换回整数
将std::位集返回到_ulong();
}

还有另一种用于计算位的方法使用表映射
countSetBit
是一种非常简单的方法
x==(int64)-1
的情况如何?因为
1是的,就像那样(有一个向上的投票),但是您确实需要检查边缘大小写
-1
。谢谢,修复了O:)有一个非分支解决方案:
int64\u t res=((1^(nb\u ones>>6))͏+͏1͏。出于兴趣,你真的觉得
0xFFFFFFFFFFFFFFFF
-1
更清晰吗?还是我是一只奇怪的猫?你来晚了,但这是最好的答案。投赞成票吧!这篇文章写得太好了,向我证明了我实现了完全错误的事情。投赞成票吧。我仍然没有任何直觉关于OP为什么需要这些位,或者它有什么用处,这可能就是为什么我花了几次阅读才弄明白的原因。
uint64_t num(uint64_t x)
{
    // construct a base-2 string
    auto s = std::bitset<64>(x).to_string();
    // sort the 1s to the end
    std::sort(begin(s), end(s));
    // and convert it back to an integer
    return std::bitset<64>(s).to_ulong();
}