有人可以在计算二进制表示中的1的数量时发现错误吗?

时间:2014-07-16 20:56:54

标签: c debugging error-handling

此代码为其他所有值输出0.对于1,它输出1.看起来它正在执行else语句,因为" temp"未打印值(已添加所有额外的打印语句以进行调试)。请帮忙。

#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;
}

4 个答案:

答案 0 :(得分:1)

那么,您想计算二进制数的人口数吗?

有什么问题
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;
}

如果你觉得这个太慢了,你可以选择&#34; bit twiddling hacks&#34; (自己谷歌,或在这个网站上搜索)。 或者,您知道,查找在一个周期内执行此操作的编译器内在函数。 Intel x86(-64):

int64_t _mm_popcnt_u64(unsigned __int64 a);

GCC

int __builtin_popcountll(unsigned long long)

答案 1 :(得分:1)

pow是一个浮点函数。因此除了可怕的慢速之外,pow(2,30)可能有舍入错误,使其略小于2,提升到30的幂,并将其分配给long long会将其向下舍入为0x3fffffff而不是0x40000000。另一方面,(1ll <&lt; 30)将在编译时进行评估,并保证给出正确的结果。

检查永远不会在循环中被修改,这就是它不起作用的原因。

您在数字-1中设置了多少位?

您能说几个位在1234567890123456中设置?为什么你不能给出那个数字的正确结果?

我说你需要一些练习才能找到解决问题最直接,最简单的方法。

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

这是直截了当的方式。你应该使用unsigned,而不是签名进行那种操作。有一些聪明的技巧可以为你提供更快的代码,但不是我希望任何人能够自己解决的问题。

答案 2 :(得分:1)

问题是for check永远不会在for循环中更新。

for(j=31;j>=2;j--){
    temp=check/2;
    if(p>=temp){
        printf("%lld temp\n",temp);
        result=1+binarysum(p-temp);
        break;
    }
} 
每次都使用检查设置

temp,但由于check没有变化,temp也没有变化。 可以将其切换为temp /= 2;,也可以使用check代替temp

答案 3 :(得分:0)

主要错误是你的递归函数不起作用。 试着仔细看看:

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);
        }
    }
}

如果假设p = 6,那么你的临界值是2 ^ 30,显然p小于临界值。所以你的递归不起作用。 声明:

result=1+binarysum(p-temp);

永远不会执行。因此,您将result设为零,因为零是存储在变量result中的垃圾值。 如果您将代码更改为:

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);
        }
    }
}

这是解决问题的简便方法

#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);
}