它们是否是更快的实现方式,无论是按位还是64位范围内的整数函数。除了我实现的那个。
/*
Find F(i)=abs(a(i)-b(i))
a(i)=number of 1's in even position
b(i)=number of 1's in odd position
for an integer i, where i fits in 64-bit
*/
//function calculate the above equation
//returns the answer
long long int F(long long int k)
{
//size of array is taken for 64-bit number
int a[64]={0},i,a,b;
long long int m;
m=k;
//convert long long int into binary
for(i=63;i>-1;i--)
{
if(m==1||m==0)
{
a[i]=m;
break; //exit the for loop
}
a[i]=m%2; //storing bit by bit
m/=2;
}
// initialized with a value of zero
a=0;
b=0;
//find first bit having 1
int f;
for(i=0;i<64;i++)
{
if(a[i]==1)
{
f=i;
break;
}
}
//calculating the number of 1's in even and odd positions
for(i=f;i<64;i++)
{
if(a[i]==1)
{
if((63-f)%2==0)
{
a++; //1's in even positions
}
else
{
b++; //1's in odd positions
}
}
}
//return the answer
return abs(a-b);
}
所以基本上我要做的是通过使用mod 2的简单方法转换其二进制表示中的整数。然后执行任务以从左到右找到其二进制表示中的第一个1并且我们的指针是在第一个号码上。现在使用第一个索引计算奇数和偶数位置的1的数量。最后返回总偶数和奇数位置1的绝对差值。
答案 0 :(得分:2)
一种简单的方法:
#include <stdint.h>
int absdiffevenoddpopcount(uint64_t x) {
uint64_t a = x & 0x5555555555555555;
uint64_t b = x & ~0x5555555555555555;
while(a && b) {
a &= a - 1;
b &= b - 1;
}
x = a ? a : b;
int r = 0;
while(x) {
x &= x - 1;
r++;
}
return r;
}
无论如何,这个页面收集了这样的位:https://graphics.stanford.edu/~seander/bithacks.html
此外,某些处理器具有特殊指令,这些指令对于(位)人口计数可能更快,通常编译器将其作为内置提供给C。
答案 1 :(得分:1)
基本上你能做的就是使用&amp;只留下奇数和偶数位。 您可以弹出两个数字,最后返回差异。 所以:
long long int F(long long int k)
{
long long int odds, evens;
odds = k & 0x5555555555555555;
evens = k & 0xaaaaaaaaaaaaaaaa;
return abs( __builtin_popcountll(odds) - __builtin_popcountll(evens));
}
我是用gcc bultin popcount写的。如果使用其他编译器,您可以在其手册中找到它。
答案 2 :(得分:1)
更加C ++友好的版本:
int F(long long const k) {
return std::abs(static_cast<int>(std::bitset<64>(k & 0x5555555555555555).count()) -
static_cast<int>(std::bitset<64>(k & 0xaaaaaaaaaaaaaaaa).count()));
}