在一个有两个';s补码,C

在一个有两个';s补码,C,c,binary,C,Binary,我想这可能有点复杂。我们应该传入一个long,然后返回数字二进制表示形式中的1的数字。对于负数,我们返回2的补码。我有积极的作用,但二的补充有点不合适。如果您有任何建议,我们将不胜感激 unsigned int binaryOnesCounter(long n) { unsigned int oneCounter, negCounter; int binaryStorage[63]; int index, negFlag; oneCounter = negFlag = ind

我想这可能有点复杂。我们应该传入一个long,然后返回数字二进制表示形式中的1的数字。对于负数,我们返回2的补码。我有积极的作用,但二的补充有点不合适。如果您有任何建议,我们将不胜感激

unsigned int binaryOnesCounter(long n) {


 unsigned int oneCounter, negCounter;
  int binaryStorage[63];
  int index, negFlag;

  oneCounter = negFlag = index = 0;


  int i;
  for (i = 0; i < 63; ++i)
  {
    binaryStorage[i] = 0;
  }

  if(n < 0) {
    if (n == -1){
      oneCounter = 63 + 1;
    } else {
      /* negate and add 1*/
      negFlag = 1;
      n = (n * -1) + 1;
    }
  }
  while (n>=1) {
    if (n%2 == 1) {
      oneCounter++;
      binaryStorage[index] = 1;
    }
    else if (n%2 == 0) {
      binaryStorage[index] = 0;
    }
    n = n/2;
  }


  if (negFlag == 1 && n != 1) {
    negCounter = 64;
    oneCounter = negCounter - oneCounter;
  }
  return oneCounter;
}
unsigned int-binaryonesconter(长n){
无符号整型计数器,负计数器;
int二进制存储[63];
int索引,negFlag;
oneCounter=negFlag=index=0;
int i;
对于(i=0;i<63;++i)
{
二进制存储[i]=0;
}
if(n<0){
如果(n==-1){
一个计数器=63+1;
}否则{
/*否定并加1*/
negFlag=1;
n=(n*-1)+1;
}
}
而(n>=1){
如果(n%2==1){
oneCounter++;
二进制存储[索引]=1;
}
否则如果(n%2==0){
二进制存储[索引]=0;
}
n=n/2;
}
如果(negFlag==1&&n!=1){
负计数器=64;
oneCounter=负计数器-oneCounter;
}
返回一个计数器;
}
它过于复杂了

int countones(long long i)
{
    int nOnes = 0;
    unsigned long long *ptr = &i;

    while (*ptr)
    {
        nOnes += *ptr & 1;
        *ptr >>= 1;
    }
    return nOnes;
}
PS-4有62个,而不是63 0B1111111111111111111111111111111111111100

这里有一个更通用的(几乎在任何对象中都计算)

int getbit(void*obj,size\u t bit);
大小/数量/通用(无效*对象,大小/通用)
{
尺寸=0,tmp=osize;
osize>3]&(1经典解决方案:

int countBits(unsigned long long x)
{
    int count = 0;
    while (x)
    {
        count++;
        x = x & (x - 1);
    }
    return count;
}

尽管我声明上面的参数为
无符号长
,但它可以修改为有符号或任何整数类型:(
char
int
,或
long
)。

一个简单的方法是使用位移位和位掩码操作,并将
n
转换为正确的表示形式(即,正值仅为
n
,负值为
n
s则为2-补码)

如果您操作的系统已经将负值表示为两个补码(大多数常见的系统都是这样),那么您只需将
n
视为无符号值,即
无符号长ul=n
。然后,
ul
将包含负值
n
的两个补码表示

如果您操作的系统以另一种形式表示负值(例如,一个补码和一个符号位),您可以自己生成两个补码:

unsigned int binaryOnesCounter(long n) {

    unsigned long ul;

    if (n < 0) {
        ul = -n;
        ul = (~ul) + 1;
    }
    else {
        ul = -n;
    }

    int count=0;
    while(ul) {
        if (ul & 0x01)
            count++;

        ul >>= 1;
    }
    return count;
}
unsigned int-binaryonesconter(长n){
无符号长ul;
if(n<0){
ul=-n;
ul=(~ul)+1;
}
否则{
ul=-n;
}
整数计数=0;
while(ul){
如果(ul&0x01)
计数++;
ul>>=1;
}
返回计数;
}
考虑实际是如何表示的

假设你有一个函数

int bits_set_in_unsigned_long(unsigned long value);
它返回以二进制形式表示的
的个数

我们可以直接向该函数提供非负输入。对于负输入,我们计算它们的两个补码(在
无符号long
中),并根据问题定义返回其中的一个数:

int bits_set_in_long(long value)
{
    if (value >= 0)
        return bits_set_in_unsigned_long( (unsigned long)value );
    else
        return bits_set_in_unsigned_long( ~(ULONG_MAX - (unsigned long)value + 1UL) + 1UL );
}
对于
ULONG_MAX
,您需要
#包括

上面的表达式

~(ULONG_MAX - (unsigned long)value + 1UL) + 1UL
(类型为
)转换为其
无符号长
二的补码。让我们看看这是如何实现的

对于二者的补码表示,我们首先需要
value
的否定值作为无符号长。然而,在许多体系结构上,
-long\u MIN==long\u MIN
,因为
long\u MAX
的大小小于
long\u MIN
。然而,因为我们知道此时该值为负数,我们可以强制转换先设置值,然后调整其负性

(无符号长)值
强制转换为
无符号长
类型。如果值在两种类型中均可表示,则值保持不变;否则,使用模运算(ISO C11,6.3.1.3)。因为此时
为负值,所以强制转换值为
加上
ULONG_MAX+1UL

因此,为了得到
-value
,我们从
ULONG_MAX+1UL
中减去强制转换值。因为
ULONG_MAX
1
是常量,编译器可能希望先将它们相加,然后抱怨它溢出了类型(它没有,因为<代码>未签名的长< /代码>类型使用模运算,我们对此非常满意。所以,我把减法放在中间,只是为了安静一些C编译器可能会发出的警告。(因为有些C编译器可能认为这种构造通常是无意中的错误,即使它们是完全标准的C代码)

换句话说,
(ULONG_MAX-(unsigned long)value+1UL)
的大小(或绝对值)作为
无符号长
,因为
此时为负值

要将其转换为2的补码格式,我们需要将它的所有二进制数字倒置(C
~
运算符完成了这一操作),最后添加一个

~(ULONG_MAX - (unsigned long)value + 1UL) + 1UL

现在,有其他方法可以用C来表达完全相同的东西,但我选择了这个p,因为两个简单的原因我不知道任何一个:第一,它是最容易证明正确的,第二,我使用的编译器(GCC)将它视为一个不可操作的架构,用两个负整数的补码表示(或者至少是我在GCC-5.4.0上测试的x86和x86-64)。换句话说,没有理由尝试“优化”表达式,除非你实际上有一个负整数的非二元补码表示的体系结构;这仅仅是因为表达式已经在二元补码体系结构上简化为零。

这是学生的练习吗?在这种情况下,这个答案可能不是你想要的,因为它没有表明你理解了他运动,但这是最喜欢的
~(ULONG_MAX - (unsigned long)value + 1UL) + 1UL
    unsigned int binaryOnesCounter(long n) {
        unsigned int nrOfOnes = __builtin_popcount((unsigned int)(n & 0xffffffff));

        nrOfOnes += __builtin_popcount((unsigned int)(n >> 32));
        return nrOfOnes;
    }
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

uint32_t count_ones (uint32_t data)
{
  static const uint8_t ONES [16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
  uint32_t count = 0;

  while(data)
  {
    count += ONES[data & 0xF];
    data >>= 4;
  }

  return count;
}

int main()
{
  uint32_t data = 0xAABBCCDD;

  printf("%"PRIu32, count_ones(data));
}