您的位置:首页 > 编程语言 > C语言/C++

iOS 学习第六天 C语言 进制转换

2016-01-12 19:32 381 查看
进制基本概念

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

# 进制转换

##1. 10进制转 2 进制

- 方法:

+除2取余, 余数倒序得到的序列就是二进制表示形式

##2. 2进制转 10 进制

- 方法:

+每一位二进制进制位的值 * 2的(当前二进制进制位索引)

>+ 索引从0开始, 从右至左

+将所有位求出的值相加

例如: 二进制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开始, 从右至左

+将所有位求出的值相加

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.原码反码补码基本概念

- 数据在计算机内部是以补码的形式储存的

- 数据分为有符号数和无符号数

+无符号数都为正数,由十进制直接转换到二进制直接存储(其实也是该十进制的补码)即可。有符号数用在计算机内部是以补码的形式储存的。( 正数的最高位是符号位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 00000000 0000 0000 0000 0001

-1反码 1111 1111 11111111 1111 1111 1111 1110

-1补码 1111 1111 11111111 1111 1111 1111 1111

>+ 正整数取反+1就是对应负数

##3.练习

- 计算分别写出-13的原码、反码、补码

-13原码:10000000 0000000000000000 00001101

-13反码:11111111 1111111111111111 11110010

-13补码:11111111 1111111111111111 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]原 + [10000001]原

= [0000 0001]反 + [11111110]反

= [1111 1111]反

= [1000 0000]原 (1111 1111,符号位不变,其他为逐位取反)

= -0

+ 发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值 上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[00000000]原和 [1000 0000]原两个编码表示0.

- 于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001]原 + [10000001]原

= [0000 0001]补 + [11111111]补

= [0000 0000]补

= [0000 0000]原

+这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001]原 + [11111111]原 = [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.什么是位运算符?

- 位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。 C语言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: