原码反码补码例子

本文详细介绍了计算机中数值的原码、反码和补码的概念,特别强调了补码的重要性。通过四个具体的计算例子,包括整数的取反、联合类型在小端机器上的表现、短整型溢出和负数的补码运算,阐述了补码运算的步骤和注意事项。例如,求解~i, -i, 1-i, -1-i的值,涉及到了补码的取反和加1操作,以及在不同情况下的数值转换。" 100692508,8446926,Django操作已有数据库及ORM使用,"['Django', 'Python', '数据库管理']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

切记:

1. 计算机中都是按照补码来存储数的

2. 规定:整数的反码,补码跟原码一样,不需求去求。而负数则符号位不变,反码各位取反,补码在反码基础上再加1.

3。 计算类似以下例子的时候,第一件事就是把结构写出来,然后看存储位数,超出的则舍弃掉。

4. 注意假设为8位,i的补码 = 1 000 0000(符号位和数字位分隔开),这种格式的数,只有补码,没有原码和反码。

5. 求10进制的值一定要用原码,见例4


1. int i = 0; i = ~i, 则i值是?

首先0=0x00000000, 取反则是0xFFFFFFFF, 即是-1的补码。或者可以按求补码的方法逆序求得原值,首先最高位是1,所以肯定是个负数。

第一步减1(这是求补码的第二步)得0XFFFFFFFE

第二步值位取反得0X80000001 所以值是-1


2. 

union Test

{

char a[4];

short b;

}


Test test;

test.a[0] = 256;

test.a[1] = 255;

test.a[2] = 254;

test.a[3] = 253;


则t在小端机器上test.b = ?

首先把test的内存结构写出来,

0xFD FE FF 00 因为256=10000 0000所以最高位1舍弃掉了。

b取两个字节,因为是小端机器,所以b结构是0xFF00,第一位是1所以肯定是负数。接下来按照第一个例子的方法算出原码是0x8100=-256.


3. short i = 65537; int j = i + 1; 则i, j值是?

首先i的二进制是0x1 0001, 但是因为是short,所以最高位要舍弃,于是就是0x0001,所以i是1,转成int,高位补0,还是1,所以j=1+1=2.

4. int i = -2147483648; 求~i, -i, 1-i, -1-i的值

首先i的16进制是8000 0000 即-2^31次方,这种格式只有补码。

取反,则是7FFF FFFF=2147483647

-i: 补码取反+1,首先取反7FFF FFFF, 然后+1, 还是8000 0000=-2147483648

1-i: -i的补码+1 = 8000 0001,所以原码是FFFF FFFF, -2147483647.

-1-i: -1的补码是FFFF FFFF, 加上-i则是7FFF FFFF,也是原码,因为是正数,所以是2147483647。


注意:计算机里的有符号跟无符号机器码(即补码)是一样的,所以要是无符号位来输出,则是2147483647, 2147483648, 2147483649, 2147483647.


### 原码反码补码的转换规则 #### 1. **原码反码之间的转换** - 对于正数,其原码反码相同。 - 对于负数,反码可以通过将原码中的符号位保持不变,其他位按位取反来获得。 示例: - 数值 `-5` 的原码为 `10000101`(假设字长为8位),则其反码为 `11111010`[^3]。 --- #### 2. **原码补码之间的转换** - 对于正数,其原码补码相同。 - 对于负数,补码可通过先求得该数的反码,然后在其基础上加 1 来获取。 示例: - 继续以上述 `-5` 为例,已知其反码为 `11111010`,那么它的补码为 `11111011`[^1]。 --- #### 3. **反码补码之间的转换** - 对于正数,其反码补码相同。 - 对于负数,补码等于反码1;反之,通过将补码减去 1 即可恢复成反码。 示例: - 已知某负数的补码为 `11111011`,将其减去 1 后得到反码 `11111010`[^2]。 --- #### C语言实现代码 以下是基于上述理论编写的用于完成各种编码之间相互转换的功能函数: ```c #include <stdio.h> // 将原码转为补码 int toTwosComplement(int num) { if (num >= 0) { return num; // 正数原码补码相同 } return (~(-num) + 1); // 负数原码补码 } // 将补码还原为原码 int fromTwosComplement(int num) { if ((num & 0x8000) == 0) { return num; // 补码为正数时不变 } return -(~(num - 1)); // 补码为负数时转原码 } // 反码补码 int onesToTwosComplement(int num) { if ((num & 0x8000) == 0) { return num; // 正数反码补码相同 } return num + 1; // 负数反码补码 } // 补码反码 int twosToOnesComplement(int num) { if ((num & 0x8000) == 0) { return num; // 正数补码反码相同 } return num - 1; // 负数补码反码 } ``` --- ### 总结 通过对不同编码形式的理解及其相互关系的学习可知,采用补码表示法能够有效解决传统原码在执行加减运算过程中遇到的一些特殊问题,比如存在两个零的情况以及无法正确处理某些边界条件等问题。因此,在现代计算机体系结构设计中广泛采用了这种机制以提高数据处理效率并减少错误发生几率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值