C语言关于进制转换,补码, 整数的位操作
菜单导航:
一、进制转换
//关于进制转换,从网上找了几张经典图片,便于后面查询
1、二进制转十进制、八进制转十进制、十六进制转十进制
2、十进制转二进制, 十进制转八进制,十进制转十六进制
3、二进制转八进制,二进制转十六进制
4、八进制转二进制,十六进制转二进制
// 编程中默认就是十进制
int num = ;
printf("十进制展示: %d\n", num); //十进制展示: 188 // 在编程中想表示二进制,需要在数字前面加上 0b
int num2 = 0b10111100;
printf("二进制 =》十进制 : %i\n", num2); //二进制 =》十进制 : 188 // 在编程中想表示八进制,需要在数字前面加上 0
int num8 = ;
printf("八进制 =》十进制 : %i\n", num8); //八进制 =》十进制 : 188 // 在编程中想表示十六进制,需要在数字前面加上 0x
int num16 = 0xbc;
printf("十六进制 =》十进制 : %i\n", num16); //十六进制 =》十进制 : 188 //以八进制形式、十六进制的形式输出十进制
printf("八进制展示:%o\n", num); //八进制展示:274
printf("十六进制展示:%x\n", num); //十六进制展示:bc
二、原码、反码、补码
/**
假如一个字节的二进制表示:最高位用来表示符号(正负)
1、原码:最容易被人脑直接识别并用于计算的表示方式
2、反码:正数的反码和原码一样,负数的反码除最高位符号位外,其他位都取反
3、补码:方便计算机进行计算,可以让最高位符号位都能参与计算;
正数的补码和原码一样,负数的补码是其反码+1
整数在计算机中以补码的方式存储,不管是正数还是负数。 举例说明:8和-8 (假如都占一个字节,最高位是0表示是正数,是1表示是负数)
8的原码:0000 1000
8的反码:0000 1000
8的补码:0000 1000
-----------------
-8的原码:1000 1000
-8的反码:1111 0111 (除最高位符号位外,其他位取反)
-8的补码:1111 1000 (负数反码+1进位) 补码的意义:让计算机运算设计更简单,可以只有加法没有减法,让符号位也参与计算
举例说明:10 - 8 = ? 和 8 - 10 = ?
a、10 - 8 = 10 + (-8) 的计算
-------- start -------
10原码: 0000 1010
-8原码: 1000 1000
-------------------
10反码: 0000 1010
-8反码: 1111 0111
-------------------
10补码: 0000 1010
-8补码: 1111 1000
补码计算结果: 10000 0010 (注意:一个字节八位,最高位符号位相加往前进1,变成最高位符号位为0,表示为正数)
二进制 0000 0010最高位为0表示是正数,正数的补码、反码、原码一样,所以补码二进制 -> 转成十进制为:2
-------- end ------ b、8 - 10 = 8 + (-10)的计算
-------- start -------
8原码: 0000 1000
-10原码: 1000 1010
--------------------
8反码: 0000 1000
-10反码: 1111 0101
--------------------
8补码: 0000 1000
-10补码: 1111 0110
补码计算结果: 1111 1110 (一个字节八位,最高位为1,表示是负数)
1111 1110 一个字节八位最高位为1表示是负数,所以此补码二进制转成十进制,需要补码减一变成反码,反码再转成原码,原码转十进制
补码 1111 1110
--> 反码(补码减1):1111 1101
--> 原码(符号位外,其他取反):1000 0010
--> 十进制:-2
-------- end ------- */
三、举例证明整数在计算机中是以补码的方式存储(以负数为例)
/*
4个字节的int类型的负数测试:-10
1000 0000 0000 0000 0000 0000 0000 1010 原码
1111 1111 1111 1111 1111 1111 1111 0101 反码
1111 1111 1111 1111 1111 1111 1111 0110 补码
*/
int num1 = 0b10000000000000000000000000001010;
int num1_2 = 0b11111111111111111111111111110110; printf("int数据类型占用字节个数:%lu\n", sizeof(int));
printf("num1: %d, %o, %x\n", num1, num1, num1);
printf("num1_2: %d, %o, %x\n", num1_2, num1_2, num1_2);
//打印结果:证明了负数在计算机中是以补码的形式存储,不是以原码的方式存储
/*
int数据类型占用字节个数:4
num1: -2147483638, 20000000012, 8000000a
num1_2: -10, 37777777766, fffffff6
*/
//num1是把-10的原码存进去,num1_2是把-10的补码存进去,打印结果显示补码转十进制才是-10,而原码转十进制是其他数字了 /**
4个字节的int类型的负数测试:-1
1000 0000 0000 0000 0000 0000 0000 0001
1111 1111 1111 1111 1111 1111 1111 1110 反
1111 1111 1111 1111 1111 1111 1111 1111 补
*/
int num2 = 0b10000000000000000000000000000001;
int num2_1 = 0b11111111111111111111111111111111;
printf("num2: %d, %o, %x\n", num2, num2, num2);
printf("num2_1: %d, %o, %x\n", num2_1, num2_1, num2_1);
//打印结果
/*
num2: -2147483647, 20000000001, 80000001
num2_1: -1, 37777777777, ffffffff
*/ /**
short数据类型负数测试:-1 (2个字节)
1000 0000 0000 0001 原码
1111 1111 1111 1110 反码
1111 1111 1111 1111 补码
*/
short num3 = 0b1000000000000001;
short num3_2 = 0b1111111111111111;
printf("short数据类型占用字节个数:%ld\n", sizeof(short));
printf("num3: %d, %o, %x\n", num3, num3, num3);
printf("num3_2: %d, %o, %x\n", num3_2, num3_2, num3_2);
//打印结果
/*
short数据类型占用字节个数:2
num3: -32767, 37777700001, ffff8001
num3_2: -1, 37777777777, ffffffff
*/
四、整数的位操作:按位且&、或|、异或^、取反~
/**
101 1000 --> 88
110 0100 --> 100 1、 88&100 按位且:一假都假;
有个小规律:任何位&1位都是该位, 比如位0&1为0位,位1&1位为1位
101 1000
&110 0100
--------
100 0000 --> 88 & 100 = 64
另外:88&100 == 88&100&88 == 88&100&100 == 88&100&100&88 2、 88|100 按位或:一真都真
101 1000
|110 0100
--------
111 1100 --> 88 | 100 = 64 + 32 + 16 + 8 + 4 = 124
另外:88|100 == 88|100|88 == 100|88|100 == 88|100|88|100 3、88^100 按位异或 : 相同为0,不同为1;
规律总结:任何数num异或另外一个数num2两次,都等于该数num
101 1000
^110 0100
--------
011 1100 --> 88^100 = 32 + 16 + 8 + 4 = 60
即:88^100^100 == 88, 88^100^88 == 100
*/ printf("0&1 = %d, 1&1 = %d \n", &, &);
printf("88 & 100 = %d, 88 | 100 = %d, 88 ^ 100 = %d\n", & , | , ^ );
printf("88&100&88: %d, 100&88&100: %d, 88&100&100&88: %d, 88|100|88: %d, 100|88|100: %d, 88|100|100|88: %d \n",
&&, &&, &&&, ||, ||, |||);
printf("88^100^88: %d, 100^88^100: %d, -88^100^-88: %d\n", ^^, ^^, -^^-);
/* 打印结果:
0&1 = 0, 1&1 = 1
88 & 100 = 64, 88 | 100 = 124, 88 ^ 100 = 60
88&100&88: 64, 100&88&100: 64, 88&100&100&88: 64, 88|100|88: 124, 100|88|100: 124, 88|100|100|88: 124
88^100^88: 100, 100^88^100: 88, -88^100^-88: 100
*/
用short类型来(占用2个字节)演示负数参与按位操作:取反、且、或、异或
/* 先分析,再验证, 以short类型2个字节为例演示
一、88取反 --> ~88 = -89
0000 0000 0101 1000
1111 1111 1010 0111 取反,为负数, 说明这个是该负数的补码
1111 1111 1010 0110 该负数反码:补码减一得反码
1000 0000 0101 1001 该负数原码 : 64 + 16 + 8 + 1 = -89
演示步骤:88原码 --> 取反得负数补码 --> 补码转反码 --> 反码转该负数原码 二、-88取反 --> ~-88 = 87
1000 0000 0101 1000 -88原码
1111 1111 1010 0111 -88反码
1111 1111 1010 1000 -88补码
0000 0000 0101 0111 -88补码取反
即-88取反的结果为:64+16+4+2+1=87
这个步骤为:-88原码 --> -88反码 --> -88补码 --> 取反 三、-88&100 负数参与按位且,分析步骤
1111 1111 1010 1000 -88补码
&0000 0000 0110 0100 100补码
-------------------
0000 0000 0010 0000 转成十进制结果为:32, 即-88&100 = 32 四、-88&-100 两个负数参与按位且,分析步骤
1000 0000 0101 1000 -88原码
1111 1111 1010 0111 -88反码
1111 1111 1010 1000 -88补码
1000 0000 0110 0100 -100原码
1111 1111 1001 1011 -100反码
1111 1111 1001 1100 -100补码
---------------------------
1111 1111 1010 1000 -88补码
&1111 1111 1001 1100 -100补码
-------------------
1111 1111 1000 1000 结果为负数,这是补码,转成原码
1111 1111 1000 0111 反码
1000 0000 0111 1000 原码,转成十进制为:-(64+32+16+8)=-120 五、-88|-100 两个负数的按位或,分析步骤
1111 1111 1010 1000 -88补码
|1111 1111 1001 1100 -100补码
--------------------
1111 1111 1011 1100 结果为负数,这是补码,转成原码为
1111 1111 1011 1011 反码
1000 0000 0100 0100 原码,转成十进制为:-(64+4)=-68 六、88^-100 有负数的按位异或,分析步骤
0000 0000 0101 1000 88原码,也是88补码
^1111 1111 1001 1100 -100补码
-------------------
1111 1111 1100 0100 结果为负数,这是补码,转成原码为:
1111 1111 1100 0011 反码
1000 0000 0011 1100 原码,转成十进制为:-(32+16+8+4)=-60 七、-88^-100 两个负数的异或,分析步骤
1111 1111 1010 1000 -88补码
^1111 1111 1001 1100 -100补码
--------------------
0000 0000 0011 0100 结果为正数,转成十进制为:32+16+4=52
*/
short number1 = 0b1111111110100111; //-89的补码
short number2 = 0b1111111110101000; //-88的补码
short number3 = 0b1111111110001000; //-120的补码
printf("number1: %d, number2: %d, number3: %d\n", number1, number2, number3);
printf("~88:%d, ~-88: %d \n", ~, ~-);
printf("-88&100: %d, -88&-100: %d \n", -&, -&-);
printf("-88|-100: %d, 88^-100: %d, -88^-100: %d \n", -|-, ^-, -^-);
/** 打印结果
number1: -89, number2: -88, number3: -120
~88:-89, ~-88: 87
-88&100: 32, -88&-100: -120
-88|-100: -68, 88^-100: -60, -88^-100: 52
*/
五、整数的位移操作:左位移,右位移 (正数、负数)
/**
以2个字节的short类型为测试数据
左位移:二进制往左移动一位,最高位左边砍掉,最低位右边补0
右位移:二进制往右移动,最低位右边砍掉,最高位左边补一个符号位(即正数补0,负数补1)
正数左位移规律:某个数num左位移n位,等于数num * 2的n次幂,比如9<<1=9*2的一次幂;9<<2=9*2的二次方幂
正数右位移规律:某数num右位移n位,等于数num/2的n次幂,比如9>>1=9/2的一次幂=4; 9>>2=9/2的2次方幂=9/4=2 一、正数的位移:
9<<1, 9<<2, 9>>1, 9>>2 0000 0000 0000 1001 // 9
000 0000 0000 1001 0 // 9<<1(9左位移1位,最高位砍掉,最低位补0,即最左边的一位砍掉,最右边补一位0)
最终为: 0 000 0000 000 1001 0 转成十进制为:16+2=18 00 0000 0000 1001 00 //9<<2 转成十进制:32 + 4= 36 0000 0000 0000 1001 //9
0 0000 0000 0000 100 // 9>>1 转成十进制:4
00 0000 0000 0000 10 // 9>>2 转成十进制:2 二、负数的位移
-9<<1, -9<<2, -9>>1, -9>>2
1000 0000 0000 1001 //-9的原码
1111 1111 1111 0110 //-9的反码
1111 1111 1111 0111 //-9的补码 //接下来补码操作进行左位移,右位移
111 1111 1111 0111 0 //-9<<1, 最新值的补码, 即-9补码往左移动一位,最高位砍掉,最低位补0
111 1111 1111 0110 1 //最新值的反码
100 0000 0000 1001 0 //最新值的原码,转成十进制为:-(16+2)=-18, 即-9<<1 = -18 11 1111 1111 0111 00 //-9<<2, 最新值的补码。即-9补码往左移动两位,左边砍掉2位,右边补两个0
11 1111 1111 0110 11 //最新值的反码
10 0000 0000 1001 00 //最新值原码,转十进制:-(32+4)=-36 1 1111 1111 1111 011 //-9>>1, 最新值的补码。即-9补码往右移动一位,最高位补符号位1,最低位砍掉
1 1111 1111 1111 010 //最新值的反码
1 0000 0000 0000 101 //最新值原码,转十进制:-(4+1)=-5 11 1111 1111 1111 01 //-9>>2, 最新值的补码. 即-9补码往右移动两位,左边补符号两位1,右边砍掉两位
11 1111 1111 1111 00 //最新值反码
10 0000 0000 0000 11 //最新值原码,转十进制:-(2+1)=-3
*/ printf("9<<1: %d, 9<<2: %d, 9>>1: %d, 9>>2: %d\n", <<, <<, >>, >>);
printf("-9<<1: %d, -9<<2: %d, -9>>1: %d, -9>>2: %d\n", -<<, -<<, ->>, ->>);
/** 打印结果:
9<<1: 18, 9<<2: 36, 9>>1: 4, 9>>2: 2
-9<<1: -18, -9<<2: -36, -9>>1: -5, -9>>2: -3
*/
六、整数的按位且&、异或^、位移的举例应用
/*
题目1、输入一个整数num, 打印该整数num的二进制
该题运用到位移、按位且&
*/
int num =;
for (int i =; i>=; i--) {
if ((i+)%==){
printf(" ");
} printf("%d", (num>>i)&);
}
printf("\n");
//打印结果为: 0000 0000 0000 0000 0000 0000 0000 1001 /**
其他几个测试记录:
101 1000 --> 88
110 0100 --> 100 1、 88&100 按位且:一假都假;
有个小规律:任何位&1位都是该位, 比如位0&1为0位,位1&1位为1位
101 1000
&110 0100
--------
100 0000 --> 88 & 100 = 64
另外:88&100 == 88&100&88 == 88&100&100 == 88&100&100&88 2、 88|100 按位或:一真都真
101 1000
|110 0100
--------
111 1100 --> 88 | 100 = 64 + 32 + 16 + 8 + 4 = 124
另外:88|100 == 88|100|88 == 100|88|100 == 88|100|88|100
即几个变量按位或后,得到的结果再和这几个变量按位或,其新结果不变 3、88^100 按位异或 : 相同为0,不同为1;
规律总结:任何数num异或另外一个数num2两次,都等于该数num
101 1000
^110 0100
--------
011 1100 --> 88^100 = 32 + 16 + 8 + 4 = 60
即:88^100^100 == 88, 88^100^88 == 100 */ /**
题目2:输入一个数字,判断该数字的奇偶性
可以多种方式实现,这里我们使用按位&来实现,
任何位&1都为该位,即0&1=0, 1&1=1
分析:整数二进制最后一位为1的是奇数,为0的是偶数
0001 1
0010 2
0011 3
0100 4
0101 5
*/
printf("奇数:%d, %d, %d, %d, %d\n", &, &, &, &, &);
printf("偶数:%d, %d, %d, %d, %d\n", &, &, &, &, &);
/** 打印结果
奇数:1, 1, 1, 1, 1
偶数:0, 0, 0, 0, 0
*/ /**
题目3:两个整数a和b, 交换两个整数的值
可以使用按位异或来处理:任何数num异或另外一个数num2两次都为该数num
*/
int a = , b = ;
//第一种方式,增加一个中间变量来交换
int c = a; a=b; b=c;
printf("第一种方式:a=%d, b=%d \n", a, b); //第二种方式
printf("第二种方式交换a: %d, b: %d的值:\n", a, b);
a = a+b;
b = a - b;
a = a - b;
printf("交换后:a=%d, b=%d \n", a, b); //第三种方式,使用^
printf("第三种方式交换a: %d, b: %d的值 \n", a, b);
a = a^b;
b = a^b; //相当于b = a^b^b = a
a = a^b; //相当于a = a^a^b = b
printf("交换后: a = %d, b = %d\n", a, b); /** 打印结果:
第一种方式:a=8, b=10
第二种方式交换a: 8, b: 10的值:
交换后:a=10, b=8
第三种方式交换a: 10, b: 8的值
交换后: a = 8, b = 10
*/ /** 题目4:整数的简单加密,使用异或^ */
int pwd = , key = ;
int encodePwd = pwd^key;
int decodePwd = encodePwd^key;
printf("原密码:%d, 加密后:%d, 解密后:%d\n", pwd, encodePwd, decodePwd);
/** 打印结果:
原密码:888888, 加密后:686414, 解密后:888888
*/
C语言关于进制转换,补码, 整数的位操作的更多相关文章
- poj2305-Basic remains(进制转换 + 大整数取模)
进制转换 + 大整数取模一,题意: 在b进制下,求p%m,再装换成b进制输出. 其中p为b进制大数1000位以内,m为b进制数9位以内二,思路: 1,以字符串的形式输入p,m; 2,转换:字符串-&g ...
- C语言基础——进制转换 / 数据表示
第一部分:进制转换 二进制:由0~1构成,逢2进1 八进制:由0~7构成,逢8进1 十六进制:由0~9.A~F构成,逢16进1 两个基本概念 基数:n进制基数为n 123.4 = 1*10^2 + 2 ...
- C语言实现进制转换——超图面试题
递归:递归的原理,就是自己调用自己本身.存在一个顺序的问题,如果在递归前的是顺序执行,递归后的是逆序执行,如下: void gogogo() { //递归之前 gogogo(); //递归之后 } 递 ...
- 一起talk C栗子吧(第七回:C语言实例--进制转换)
各位看官们.大家好,从今天開始.我们讲大型章回体科技小说 :C栗子,也就是C语言实例. 闲话休提, 言归正转.让我们一起talk C栗子吧! 看官们.上一回中咱们说的是生成随机数的样例.这一回咱们说的 ...
- C语言实现进制转换
#include<stdio.h> int main() { char ku[16]={'0','1','2','3','4','5','6','7','8','9','A','B ...
- C语言基础:进制转换,变量,常量,表达式,基本数据类型,输出函数,输入函数,运算符. 分类: iOS学习 c语言基础 2015-06-10 21:39 25人阅读 评论(0) 收藏
二进制:以0b开头,只有0和1两种数字.如0101 十进制:0~9十个数字表示.如25 十六进制:以0~9,A~F表示,以0X开头.如0X2B 十进制转换为X进制:连除倒取余 X进制转换为十进制:按权 ...
- C语言 进制转换
这个程序仅仅是由十进制转换为其他进制的过程,其转换的规则如下图所示. 我使用的思路:首先在除基的过程中用一个数组保存余数,然后在输出进制转换结果的时候倒序输出,并且在输出前判断余数是否大于10,如果大 ...
- 大数据学习--day02(标识符、变量、数据类型、类型转换、进制转换、原码反码补码)
标识符.变量.数据类型.类型转换.进制转换.原码反码补码 标识符: java50个关键字不能做标识符,以数字开头不能做标识符(这个老是忘记写一个类名的时候) 变量: 变量分为成员变量和局部变量,注意作 ...
- python3笔记二:进制转换与原码反码补码
一:学习内容 进制:二进制.八进制.十进制.十六进制 进制转换 原码.反码.补码 二:进制 二进制 1.二进制:只有0和1,逢2进1 2.举例:0+0=0.0+1=1.1+1=10 3.过程剖析:二进 ...
随机推荐
- SharePoint 2013 SqlException (0x80131904):找不到Windows NT 用户或组xxxx\administrator
过程描述: 在SharePoint 2013里配置创建搜索服务应用程序时报错: 配置 Search Service 应用程序期间遇到错误. System.Data.SqlClient.SqlExcep ...
- bootstrap4简单使用和入门03-响应式布局
响应式布局的原理 页面源码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...
- Kendo ui 入门知识点
1. Kendo的继承 varPerson= kendo.Class.extend({...}); var person = new person(); var Parent = kendo.Clas ...
- workflow的简介
工作流(Workflow) 是对工作流程及其各操作步骤之间业务规则的抽象.概括描述.工作流建模,即将工作流程中的工作如何前后组织在一起的逻辑和规则,在计算机中以恰当的模型表达并对其实施计算. 工作流要 ...
- 利用zxing生成二维码
使用zxing类库可以很容易生成二维码QRCode,主要代码如下: private Bitmap createQRCode(String str,int width,int height) { Bit ...
- LINUX-redis & mongodb
ubuntu安装redis: apt-get -y install redis-serverubuntu启动redis: /etc/init.d/redis-server restart linux安 ...
- 对mysql数据库中字段为空的处理
数据库中字段为空的有两种:一种为null,另一种为空字符串.null代表数值未知,空字符串是有值得,只是为空.有时间我们想把数据库中的数据以excel形式导出时 如果碰到字段为空的,为空的字段会被后面 ...
- python的学习笔记
1逻辑运算符不理解 2 在交互模式中,最后被输出的表达式结果被赋值给变量 _ .例如: >>> tax = 12.5 / 100 >>> price = 100.5 ...
- iOS 去除百度地图下方的 logo
UIView *mView = _mapView.subviews.firstObject; for (id logoView in mView.subviews) { if ([logoView ...
- Confluence 6 针对站点维护使用只读模式
如果你需要对 Confluence 进行维护,但是 Confluence 还是在运行或者你计划将站点合并到一个新的站点,你可以将你的 Confluence 站点设置为只读模式来限制用户在你站点中可以使 ...