在一个有两个';s补码,C
我想这可能有点复杂。我们应该传入一个long,然后返回数字二进制表示形式中的1的数字。对于负数,我们返回2的补码。我有积极的作用,但二的补充有点不合适。如果您有任何建议,我们将不胜感激在一个有两个';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
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));
}