进制基本概念
本小节知识点:
- 【了解】什么是进制?
- 【理解】常见的进制
- 【了解】编程输出各种进制
1.什么是进制?
- 是一种计数的方式,数值的表示形式
2.常见的进制
- 十进制、二进制、八进制、十六进制
3.进制数字进位方法
-
十进制 0、1、2、3、4、5、6、7、8、9 逢十进一
-
二进制 0、1 逢二进一
- 书写形式:需要以0b或者0B开头,比如0b101
-
八进制 0、1、2、3、4、5、6、7 逢八进一
- 书写形式:在前面加个0,比如045
-
十六进制 0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F 逢十六进一
- 16进制就是逢16进1,但我们只有0~9这十个数字,所以我们用A,B,C,D,E,F这五个字母来分 别表示10,11,12,13,14,15。字母不区分大小写。
- 书写形式:在前面加个0x或者0X,比如0x45
-
数一下方块的个数, 并用十进制,二进制,八进制,十六进制表示
-
练习
1.判断下列数字是否合理 00011 0x001 0x7h4 10.98 0986 .089-109 +178 0b325 0b0010 0xffdc 96f 96.0f 96.oF -.003
4.编程输出各种进制
- 假设有整型变量a,初始值为13,打印其8进制、16进制测试
int a = 13; printf("10->8: %o\n", a); printf("10->16: %x\n", a);
- 定义一个二进制数、八进制数、十六进制,打印其对应的10 进制
int a = 0b00000000000000000000000000001101;
printf("2->10: %d\n", a);
a = 015;
printf("8->10: %d\n", a);
a = 0xd;
printf("16->10: %d\n", a);
输出结果:
2->10: 13
8->10: 13
16->10: 13
进制转换
本小节知识点:
- 【掌握】10 进制转 2 进制
- 【掌握】2 进制转 10 进制
- 【掌握】2 进制转 8 进制
- 【掌握】8 进制转 2 进制
- 【掌握】2 进制转 16 进制
- 【掌握】16 进制转 2 进制
1.10 进制转 2 进制
-
方法:
- 除2取余, 余数倒序得到的序列就是二进制表示形式
-
例如:将十进制(97) 10转换为二进制数
2.2 进制转 10 进制
- 方法:
- 每一位二进制进制位的值 * 2的(当前二进制进制位索引)
- 索引从0开始, 从右至左
- 将所有位求出的值相加
- 每一位二进制进制位的值 * 2的(当前二进制进制位索引)
例如: 二进制11转换为10进制
0b1011 = 1 * 2^0 + 1 * 2^1 + 0 * 2^2 + 1 * 2^3
= 1 * 1 + 1 * 2 + 0 * 4 + 1 * 8
= 1 + 2 + 0 + 8
= 11
3.2 进制转 8 进制
- 三个二进制位代表一个八进制位, 因为3个二进制位的最大值是7,而八进制是逢八进一
0b11110011 = 0b 011 110 011
= 0363
4.8 进制转 2 进制
- 方法:
- 每一位八进制位的值 * 8的(当前二进制进制位索引)
- 索引从0开始, 从右至左
- 将所有位求出的值相加
- 每一位八进制位的值 * 8的(当前二进制进制位索引)
027 = 7 * 8^0 + 2 * 8^1
= 7 * 1 + 2 * 8
= 23
3.2 进制转 16 进制
- 四个二进制位代表一个十六进制位,因为4个二进制位的最大值是15,而十六进制是逢十六进一
例如: 二进制243转换为16进制
0b11110011 = 0b 1111 0011
= 0xF3
4.16 进制转 2 进制
- 将16进制的每一位拆成4为二进制位
例如:
0x25 =0b 0010 0101
=0b100101
机器数和真值的概念
原码反码补码概念及转换
本小节知识点:
- 【理解】原码反码补码基本概念
- 【理解】-1在内存中存储细节
- 【理解】练习
1.原码反码补码基本概念
- 数据在计算机内部是以补码的形式储存的
-
数据分为有符号数和无符号数
- 无符号数都为正数,由十进制直接转换到二进制直接存储(其实也是该十进制的补码)即可。 有符号数用在计算机内部是以补码的形式储存的。( 正数的最高位是符号位0,负数的最高位是 符号位1。 对于正数:反码==补码==原码。 对于负数:反码==除符号位以外的各位取反。补码=反 码+1)
- 正数的首位地址为0,其源码是由十进制数转换到的二进制数字
- 负数的首位地址为1,其源码后面的位也为10进制数转换过去的二进制数字,都是用补码方式表示 有符号数的。
-
在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要 使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式. 原码, 反码, 补码是计算机原理的术语。说白了就是为了理解计算机2进制用的。对于C/C++来 说,是和数据类型有关的。
-
原码
- 原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值
原码:[+1]0000 0001 原码:[-1]1000 0001
- 原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值
-
反码
- 正数的反码是其本身
- 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
原码:[+1]0000 0001 反码:0000 0001 原码:[-1]1000 0001 反码:1111 1110
- 可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计 算.
- 补码
- 正数的补码就是其本身
- 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
原码:[+1]0000 0001 反码:0000 0001 补码:0000 0001 原码:[-1]1000 0001 反码:1111 1110 补码:1111 1111
- 对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.
2.-1在内存中存储细节
- 在64为计算机中,-1的原码、反码、补码如下
-1原码 1000 0000 0000 0000 0000 0000 0000 0001 -1反码 1111 1111 1111 1111 1111 1111 1111 1110 -1补码 1111 1111 1111 1111 1111 1111 1111 1111
- 正整数取反+1就是对应负数
3.练习
- 计算分别写出-13的原码、反码、补码
-13原码:10000000 00000000 00000000 00001101 -13反码:11111111 11111111 11111111 11110010 -13补码:11111111 11111111 11111111 11110011
原码反码补码练习
本小节知识点:
- 【掌握】为什么要引入反码和补码?
- 【了解】补码的再深入
1.为什么要引入反码和补码?
-
在开始深入学习前, 我的学习建议是先"死记硬背"上面的原码, 反码和补码的表示方式以及计算方法.
-
现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同, 所以不需要过多解释
原码:[+1]0000 0001
反码:[+1]0000 0001
补码:[+1]0000 0001
- 但是对于负数, 可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何 还会有反码和补码呢?
原码:[-1]1000 0001 反码:[-1]1111 1110 补码:[-1]1111 1111
- 首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的 加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的 尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了 将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.
2.补码的再深入
-
计算十进制的表达式: 1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
- 如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算 机内部不使用原码表示一个数.
-
为了解决原码做减法的问题, 出现了反码:
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 (1111 1111,符号位不变,其他为逐位取反) = -0
- 发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值 上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和 [1000 0000]原两个编码表示0.
-
于是补码的出现, 解决了0的符号以及两个编码的问题:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补 = [0000 0000]原
- 这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128: (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补
- -1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际 上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)
-
单字节的表示的最大的负数是多少? ``` [10000000]补 =[10000000]反+1 =11111111+1 =(1)00000000 =00000000(最高位溢出了,符号位变成了0)
有人会问 10000000这个补码表示的哪个数的补码呢? 其实这是一个规定,这个数表示的是-128 所以n位补码能表示的范围是 -2^(n-1)到2^(n-1)-1 比n位原码能表示的数多一个
- 所以得出整型数的数值范围:
int number1 = 0b10000000000000000000000000000000;
int number2 = 0b01111111111111111111111111111111;
int number3 = 0b11111111111111111111111111111111;
printf("number1 = %d\n", number1);
printf("number2 = %d\n", number2);
printf("number3 = %d\n", number3);
输出结果: number1 = -2147483648 number2 = 2147483647 number3 = -1
```
位运算符介绍(一)
1.本小节知识点:
- 【掌握】什么是位运算符?
- 【掌握】位运算符与
- 【掌握】位运算符或
- 【掌握】位运算符异或
- 【掌握】位运算符取反
- 【掌握】练习
1.什么是位运算符?
- 位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。 C语言