OpenJudge NOI 1.13 35:输出二进制补码

【题目链接】

OpenJudge NOI 1.13 35:输出二进制补码

【题目考点】

1. 机器码
  • 非负数的原码、反码、补码相同。
  • 负数
    • 原码:符号位是1
    • 反码:各位取反,符号位不变
    • 补码:反码加1,符号位不变
2. 数制
3. 高精度
4. 位运算

【解题思路】

解法1:使用数字数组

使用数字数组a,从低位到高位保存机器码的各个数位,模拟求补码的过程。
如果数字n是负数,那么将a的最高位(第32位)设为1,将n变为n的相反数,变成正数。
而后对数字n做二进制下的数字拆分,将n转为二进制数字,填充到数字a。当前数组a就是数字n的原码。

  • 如果n是非负数,那么原码就是补码,直接输出数组a。
  • 如果n是负数,而后对第1到第31位取反,得到反码。接着对这个反码加1,方法为:从低位开始,只要遇到1,就将其变为0,再看下一位。直到遇到一个0,将这个0变为1,结束。

已知32位的有符号整型可以表示的数字范围为: − 2 32 ∼ 2 32 − 1 -2^{32}\sim2^{32}-1 2322321 − 2 32 -2^{32} 232这个数字的补码很特别,是1后面接31个0。最高位第32位既是符号位表示负数,又表示数值。
− 2 32 -2^{32} 232在十六进制下为 0 x 80000000 0x80000000 0x80000000,十进制下为 − 2147483648 -2147483648 2147483648。如果输入的是这个值,根据上述逻辑,对这个值取反,会得到2147483648,也就是 2 32 2^{32} 232,而这个值是无法用int类型表示的,用int类型保存这个值会产生错误。
因此,为了能够让 − 2 32 -2^{32} 232成功取反,变量n及相关变量要声明成long long。

解法2:使用位运算

数字在计算机内存中都是以补码形式保存的,也就是说机器码都是补码。而位运算正是处理变量的机器码的运算。
输入数字n,循环32次,每次循环做:

  • 取数字n机器码的最低位(n%2是做不到的,因为n为负数时取模会得到负数)。这里要使用按位与(&),用n按位与1:如果n的最低位是1,结果就是1。如果n的最低位是0,结果就是0。所以n&1就是n这个数字的机器码的最低位。将这个数字变为字符,接在表示补码的字符串上。
  • 而后让n去掉刚才已经取出的一位,即右移一位,写法为n = n>>1n >>= 1

最后输出拼接后的表示补码的字符串。
注意:按位与&的运算优先级比算术运算符低,使用时要加括号。

【题解代码】

解法1:使用数字数组 模拟
#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long n;
    int a[33] = {}, ai = 0;
    cin >> n;
    if(n < 0)
    {
        a[32] = 1;
        n = -n;
    }
    for(long long i = n; i > 0; i /= 2)
        a[++ai] = i%2;
    if(a[32] == 1)
    {
        for(int i = 1; i < 32; ++i)
            a[i] = !a[i];
        for(int i = 1; i < 32; ++i)
        {
            if(a[i] == 1)
                a[i] = 0;
            else
            {
                a[i] = 1;
                break;
            }
        }
    }
    for(int i = 32; i >= 1; i--)
        cout << a[i];    
    return 0;
}
解法2:使用位运算
#include <bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    int n;
    cin >> n;
    for(int i = 1; i <= 32; ++i)
    {
        s = char((n&1)+'0')+s;
        n >>= 1;
    }
    cout << s;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值