进制转化
- 一个数字的大小本质上都是表示状态数的多少
- 数字的表示可以用不同的进制
- 十进制转r进制:整数部分–除r取余,直至商0,余数倒置即可,小数部分–乘r取整,直至积为0,整数正序排列即可
- 二进制转10进制:8421码
补码的相关知识
在介绍补码之前先来认识其他的一些二进制码:
1、原码:
也叫符号—绝对值码,最高位0表示正、1表示负,其余二进制是该数字的绝对值的二进制位
如-5的原码是10101, 原码简单易懂,但是它加减复杂,存在加减乘除四种运算,增加了CPU的复杂度
还有就是源码制下0的表示不唯一,所以源码在计算机中从来不使用。
2、反码:
对原码每一位取反,在计算机中基本无使用
3、移码:
表示数值平移n位,(n称为移码量),移码主要用于浮点数阶码的存储
以上为认识补码的相关背景知识。
那么什么是补码呢?为什么要引入补码?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
补码的特性:
- 一个整数的原码与其补码相加,和为模
- 对一个整数的补码再求补码,等于该整数自身
- 补码的正零与负零表示方法相同
通过源码求补码:
[+73]补 = 01001001
[-73]补 = 100000000 - 01001001 = 10110111
[+1]补 = 00000001
[-1]补 = 100000000 - 00000001 = 11111111
[+127] = 01111111
[-127] = 100000000 - 01111111 = 10000001
综上:
1. 整数的补码与其原码相同
2. 0的补码仍然为0
3. 负数的补码可以通过其正数的原码“取反加一”,并且最高符号位也参与运算得到
扩展:
根据补码的定义,可以证明:
[X]补 + [Y]补 = [X+Y]补
[X]补 - [Y]补 = [X-Y]补
这表明,两个补码加减的结果也是补码,而且在运算时,符号位可同数值部分作为一个整体参加运算,如果符号位有进位则舍弃进位。
计算机中的加减运算:
如:4-6=?
0000 0100
+ 0000 0110-->1111 1001-->1111 1010
-----------------------------------
1111 1110 (所得结果为补码,符号位为负)-->0000 0001-->0000 0010
故最终结果为 -2
[注] 一个数的补码为(1111 1110),求其数值?
分析:最高位为1,则该数肯定为负数,并且我们知道“补码的补码就是其对应的非负数值”,求得0000 0010,
故这个数的数值为 -2。
程序演示:
/**
* 计算机二进制运算程序演示
*/
# include <stdio.h>
int main() {
int a = 0;
short int i = -3;
int j = -3;
long int k = -3;
char m = 'A';
int n = 0XFFFFFFE1; //11111111111111111111111111100001 //负数最高符号位均补1
printf("%#X\n",a); //0
printf("%#X\n",i); //0XFFFFFFFD
printf("%#X\n",j); //0XFFFFFFFD
printf("%#X\n",k); //0XFFFFFFFD
printf("%#X\n",m); //0X41
printf("%d\n",n); //-31
return 0;
}
常见的位运算符
- 按位与&
- 按位或|
- 按位取反\~
- 按位异或^
- 按位左移和按位右移 \<< >>
/*
5&7=5
5&-7=1
5|7=7
5|-7=-3
~5=-6
~7=6
5^7=2
5^-7=-4
5<<1=10
-7<<1=-14
5>>1=2
-7>>1=-4
*/
# include <stdio.h>
int main() {
printf("5&7=%d\n", 5&7); //5的二进制补码是...0101,7的二进制补码是...0111,两者相与后补码变为...0101,输出十进制结果为5
printf("5&-7=%d\n", 5&-7); //5的二进制补码为00000101,-7的二进制补码为11111001,5&-7=00000001,即输出结果为1
printf("5|7=%d\n", 5|7); //5的二进制补码为00000101,7的二进制补码为00000111,5|7=00000111,即输出结果为7
printf("5|-7=%d\n", 5|-7); //5的二进制补码为00000101,-7的二进制补码为11111001,5|-7=,结果的补码为11111101,是个负数,结果为-3
printf("~5=%d\n", ~5); //5的二进制补码为00000101,则~5=11111010,是个负数,结果为-6
printf("~7=%d\n", ~-7); //-7的二进制补码为11111001,则~-7=00000110,结果为6
printf("5^7=%d\n", 5^7); //5的二进制补码为00000101,7的二进制补码为00000111,5^7=00000010,结果为2
printf("5^-7=%d\n", 5^-7); //5的二进制补码为00000101,-7的二进制补码为11111001,5^-7=111111100,结果为-4
printf("5<<1=%d\n", 5<<1); //5的二进制补码为00000101,5<<1=00001010,结果为10
printf("-7<<1=%d\n", -7<<1); //-7的二进制补码为11111001,-7<<1=11110010,结果为-14
printf("5>>1=%d\n", 5>>1); //5的二进制补码为00000101,5>>1=00000010,结果为2
printf("-7>>1=%d\n", -7>>1); //-7的二进制补码为11111001,-7>>1=11111100,结果为-4
return 0;
}