关于将一个数输出为原码、反码和补码的解惑

有这么一道题目:

编写函数,实现输入一个数,输出该数的原码、反码和补码

一开始我并没有用位运算的思路,于是写下了下面长长的一段代码:
(假设我输入-1754)

#include <stdio.h>
#include <math.h>

int positive(int num) //用于计算正数
{
    int i,a[1000],b=1,c;
    for (i=0; i<1000; i++) {
        a[i]=num%2;
        num=num/2;
        if (num<1)
        {
            b=i;
            break;
        }
    }
    a[b+1]=0;
    printf("ture code is ");
    for (i=b+1; i>=0; i--)
    {
        printf("%d",a[i]);
    }
    printf("\nones-complement code is ");
    for (i=b+1; i>=0; i--) {
        c=a[i];
        c=~c&1;   //必须要有,不然会11111111的c
        printf("%d",c);
    }
    printf("\ncomplemental code is ");
    for (i=b+1; i>=0; i--)
    {
        printf("%d",a[i]);
    }
    printf("\n");
    return 0;
}

int negetive(int num)  //计算负数
{
    int i,a[1000],d[1000],b=1,c,e = 0,numb;
    numb=num;
    num=-num;
    for (i=0; i<1000; i++) {
        a[i]=num%2;
        num=num/2;
        if (num<1)
        {
            b=i;
            break;
        }
    }
    num=-numb;
    num=~num;  //此处num输出会出现-1755,原因是现在机器普遍用补码表示负数
    num=num+1;
    printf("%d\n",num);
    for (i=0; i<1000; i++) {//注意此处for循环是错误的
        d[i]=num%2;
        num=num/2;
        if (num>-1)
        {
            e=i;
            break;
        }
    }
    a[b+1]=1;
    d[e+1]=1;
    printf("ture code is ");
    for (i=b+1; i>=0; i--)
    {
        printf("%d",a[i]);
    }
    a[b+1]=0;
    printf("\nones-complement code is ");
    for (i=b+1; i>=0; i--) {
        c=a[i];
        c=~c&1;   //必须要有不然会11111111
        printf("%d",c);
    }
    printf("\ncomplemental code is ");
    for (i=e+1; i>=0; i--)
    {
        printf("%d",d[i]);
    }
    printf("\n");
    return 0;
}

int main()  //主程序
{
    int num;
    printf("please input a number:\n");
    scanf("%d",&num);
    if (num>0) {
        positive(num);
    }
    else if (num==0)
        printf("0000000000000000\n1111111111111111\n0000000000000000");
    else
        negetive(num);
}

没有引入位运算会使得整个代码冗长,不过复杂无所谓,正确就可以了。
可是他不正确啊。。对于正数的输出是无问题的,一旦进入负数,其补码就会错误。
为什么呢?我们把负数for循环部分单独拎出来看一下:

num=-numb; //第一步让num重新变为1754
    num=~num;  //对1754求反码,此处num输出会出现-1755,原因是现在机器普遍用补码表示负数,于是求完反码之后机器直接认为此处是一个补码,就会按照补码的读取方式读取
    num=num+1;  //此处是对-1755+1=-1754
    for (i=0; i<1000; i++) //注意此处for循环是错误的,将-1754输入进入了循环
    {
        d[i]=num%2;  // 此处都是负数
        num=num/2;
        if (num>-1)
        {
            e=i;
            break;
        }
    }  // 因为是负数,这样一来后面输出就会出错

于是我采用位运算写法简化了二进制输出:

  for(i=15;i>=0;i--)  //默认16位
        {
            b=a>>i;     //每次循环逐个读取最后一个数
            b=b&~(~0<<1);   //此处xcode会报警报提示未定义的左移,可以用b=b&~(~0-1)来代替
            printf("%hd",b); 
        }
    }

这串代码甚至不需要对正负数进行区分,如果是负数机器默认就是用补码储存,故直接读出来就可以了。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个输出原码反码补码的例子: ```python num = -18 bits = num.bit_length() + 1 print("原码:", bin(num & ((1 << bits) - 1))) print("反码:", bin(num & ((1 << bits) - 1) ^ ((1 << bits) - 1))) print("补码:", bin(num & ((1 << bits) - 1) ^ ((1 << bits) - 1) - 1)) ``` 输出结果为: ``` 原码: -0b10010 反码: -0b10011 补码: -0b10010 ``` 其中,`num.bit_length()`用于获取`num`的二进制表示的位,`bits`为二进制表示的位加1,`1 << bits`为一个二进制,其最高位为1,其余位为0,表示一个比`num`的二进制表示的位多1的二进制。`((1 << bits) - 1)`为一个二进制,其所有位都为1,表示一个比`num`的二进制表示的位多1的全1二进制。`num & ((1 << bits) - 1)`用于将`num`的二进制表示截取为`bits`位,即去掉多余的高位。`((1 << bits) - 1) ^ ((1 << bits) - 1)`为一个二进制,其所有位都为0,表示一个比`num`的二进制表示的位多1的全0二进制。`num & ((1 << bits) - 1) ^ ((1 << bits) - 1)`用于将`num`的二进制表示的符号位取反,即将其变为反码。`((1 << bits) - 1) ^ ((1 << bits) - 1) - 1`为一个二进制,其最高位为0,其余位为1,表示一个比`num`的二进制表示的位多1的全1二进制减1,即一个比`num`的二进制表示的位多1的全1二进制补码。`num & ((1 << bits) - 1) ^ ((1 << bits) - 1) - 1`用于将`num`的二进制表示的符号位取反并加1,即将其变为补码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值