简体   繁体   中英

Can someone find the error in calculating number of 1's in binary representation?

This code is outputting 0 for all values other 1. For 1 it is outputting 1. It looks like it is the executing the else statement because "temp" value is not being printed (All extra print statements have been added for debugging). Please help.

#include<stdio.h>
#include<math.h>
int binarysum(long long int p);
int main(){
    int r;
    long long int x;
    scanf("%lld",&x);
    r=binarysum(x);
    printf("%d",r);
    return 0;
}
int binarysum(long long int p){
    int result;
    int j;
    long long int check=pow(2,30),temp;
    printf("%lld p %lld check\n",p,check);
    if(p==0)
        result=0;
    else if(p==1)
        result=1;
    else{
        for(j=31;j>=2;j--){
            temp=check/2;
            if(p>=temp){
                printf("%lld temp\n",temp);
                result=1+binarysum(p-temp);
                break;
            }
        } 
    }
    printf("%d result\n",result);
    return result;
}

So, you want to calculate a population count on a binary number?
What's wrong with

int popcount(unsigned long long a)
{
    int retval = 0;
    size_t i;
    unsigned long long b = 1;
    for (i = 0; i<(CHAR_BIT*sizeof(unsigned long long); i++)
    {
        if (a & b<<i)
           retval++;
    }
    return retval;
}

If you should find this too slow, you could go with the appropriate section of "bit twiddling hacks" (google it yourself, or search on this site). Or, you know, look up compiler intrinsics that do it in one cycle. Intel x86(-64):

int64_t _mm_popcnt_u64(unsigned __int64 a);

gcc:

int __builtin_popcountll(unsigned long long)

pow is a floating-point function. So apart from being horrifically slow, pow (2, 30) may have rounding errors that make it a bit smaller than 2 raised to the power of 30, and assigning it to a long long will round it down to 0x3fffffff instead of 0x40000000. On the other hand, (1ll << 30) will be evaluated at compile time, and is guaranteed to give the correct result.

check is never modified in the loop, which is why it doesn't work.

How many bits would you say are set in the number -1?

How many bits would you say are set in the number 1234567890123456? Why wouldn't you give the right result for that number?

I'd say you need a bit of practice to find the most direct and simplest way to solve a problem.

int bitcount = 0; 
for (long long mask = 1ll << 62; mask != 0; mask >>= 1)
    if ((p & mask) != 0)
        ++bitcount;

That's the straightforward way to do it. You should really use unsigned, not signed for that kind of operation. There are clever tricks that give you faster code, but not what I would expect anyone to figure out on their own.

The problem is that check is never updated in the for loop.

for(j=31;j>=2;j--){
    temp=check/2;
    if(p>=temp){
        printf("%lld temp\n",temp);
        result=1+binarysum(p-temp);
        break;
    }
} 

temp is set using check every time, but since check doesn't change, neither does temp . Either switch it to temp /= 2; , or use check instead of temp .

The main error is that your recursive function is not working. Try to take a close look:

if(p==0)
    result=0;
        else if(p==1)
    result=1;
else{
    for(j=31;j>=2;j--){
        temp=check/2;
        printf("temp=%lld\n",temp);
        if(p>=temp){
            printf("%lld temp\n",temp);
            result=1+binarysum(p-temp);
        }
    }
}

If suppose p=6 then your temp is 2^30 clearly p is less than temp. So your recursion doesn't work. The statement:

result=1+binarysum(p-temp);

never executes. So you get result as zero because zero is the garbage value stored in the variable result . if you change your code to:

else{
    temp=check;
    for(j=31;j>=2;j--){
        temp=temp/2;
        printf("temp=%lld\n",temp);
        if(p>=temp){
            printf("%lld temp\n",temp);
            result=1+binarysum(p-temp);
        }
    }
}

Here is easy way to solve your problem

#include<stdio.h>
int main(){
    long long number;
    scanf("%lld",&number);
    int result=0;
    while(number>0){
        if(number&1){
            result++;
        }
        number=number>>1;
    }
    printf("%d\n",result);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM