(二十)位运算与进制

一、前言

你听说过进制吗?你知道进制怎么表示吗?你知道进制如何转换吗?这篇帖子就能get进制。另外,在二进制中,我们还会用到位运算符号

二、正文

(一)位运算

  1. a&b:按位与,写作AND,相同二进制数位对齐(如果是其他进制则会自动转换),各个位进行比较,如果相同位上两值都为1,则将结果的那一位也写为1,否则写为0
    10110
AND 10111
-----------
    10110
  1. a|b:按位或,写作OR,相同二进制数位对齐,各个数位进行比较,若两个相同数位中至少有一个的值为1,那么结果的那一位写为1,否则写为0
   10010
OR 10111
----------
   10111
  1. a^b:按位异或,写作XOR,相同二进制数位对齐,各个数位进行比较,若两个相同数位不相等,那么结果的那一位就写为1,否则写为0
    10001
XOR 10110
-----------
      111
  1. ~n:按位取反,1变0,0变1
1011001
-------
 100110
  1. n<<m:将n向左移动m位,前位缺位就补0
       1111010
<<          10 → 2
    ----------
     111101000
  1. n>>m:将n向右移动m为,缺位就删数
    111010
<<      10 → 2
----------
      1110

(二)进制

1. 进制的定义

(1) 二进制(BIN)

只有0和1两个数字,加法遵循“逢二进一”的原则,减法遵循“借一为二”原则。二进制数 1010010 1010010 1010010写作 ( 1010010 ) 2 (1010010)_{2} (1010010)2 0 b 1010010 0b1010010 0b1010010 1010010 B 1010010B 1010010B。这是计算机中经常使用的,因此使用位运算会大大降低运算复杂度

(2) 八进制(OCT)

有数字0~7,加法遵循“逢八进一”的原则,减法遵循“借一为八”原则。八进制数 17 17 17写作 ( 17 ) 8 (17)_{8} (17)8 0 o 17 0o17 0o17或者 17 O ( 字母 ) 17O(字母) 17O(字母)

(3) 十进制(DEC)

这个不用说了吧,在生活中常用数字。十进制数 95 95 95写作 95 D 95D 95D ( 95 ) 10 (95)_{10} (95)10,也可以直接写

(4) 十六进制(HEX)

从0~F的数字,在9后,10用A或a表示,11用B或b表示,……,15用F或f表示。加法遵循“逢十六进一”原则,减法遵循“借一为十六”原则

2. 进制表

这是个人创作的,允许转发、使用、借鉴
进制转换表

3. 进制转换

(1) 10进制转D进制

一般我们都是把10进制转换为2进制,整数部位使用短除法的形式,依次除以D,将余数写在右边,最终将余数从下往上读;小数部位使用乘法的形式,依次乘D,若这个数大于一个整数,就在竖式右边写上那个整数,随后将结果减去整数,否则在右边写上0,直到最终结果为整数,再从上往下读(题目一般会给出精度)

如何使用编程实现呢?

输入共两行,分别表示整数(N)和进制(D)
输出共一行,表示N的D进制

#include <iostream>//输入输出流 
#include <string>//输出结果 
using namespace std; 
inline char tochr(short n) {//将数字转换为字符 
	if(n<10) 
		return n+48; //'0'的ASCII码是48
	if(n>=10&&n<16) 
		return n+55; //'A'的ASCII码是65
}
int main() {
	unsigned long long n; //原数 
	short d; //进制 
	cin >> n >> d; 
	string s; //结果 
	while(n) {//也可以写成while(n!=0) 
		s = tochr(n%d) + s; //转换 
		n /= d; //获得商 
	} 
	while(s[0]=='0') s.erase(0, 1); //删除前导0 
	if(s.empty()) s = "0"; //n为0的情况 
	cout << s; 
	return 0; 
}
(2) D进制转十进制

我们可以使用位权法进行转换,比如将二进制数1101转换为十进制
( 1101 ) 2 = 2 3 + 2 2 + 2 0 = 8 + 4 + 1 = 13 (1101)_{2} = 2^{3}+2^{2}+2^{0} = 8+4+1=13 (1101)2=23+22+20=8+4+1=13
又如何实现呢?

输入共两行,分别表示数字(N)和进制(D)
输出共一行,表示它的十进制

#include <iostream>//输入输出 
#include <string>//输入 
#include <cmath>//进行幂运算 
#include <algorithm>//颠倒输入 
using namespace std; 
short todig(char c) {//将字符转换为数字形式 
	if(c>='A'&&c<='F')
		return c-55; 
	if(c>='0'&&c<='9')
		return c-48; 
}
int main() {
	string s; //输入 
	short d; //输入进制 
	cin >> s >> d; 
	long long r = 0; //结果 
	reverse(s.begin(), s.end()); //颠倒输入 
	for(int i=s.length()-1, t=todig(s[i]); i>=0; i--, t=todig(s[i])) //使用i遍历项数,用t遍历每一项的数字形式 
		r += t*pow(d,i); 
	cout << r; 
	return 0; 
}
(3) 二进制转八进制

二进制和八进制可以使用“三合一”法,意思是将二进制三位三位分(前补0),然后再分别转换为它的八进制数,点击我见此表0~7项BIN和OCT的关系

#include <bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin>>s;
    if(s=="0"){//排除是0的情况
        cout<<0;
        return 0;
    }
    while(s.length()%3) s="0"+s; //补0
    for(int i=0;i<s.length();i+=3){
        string tmp=s.substr(i,3);
        if(tmp=="000") cout<<'0';
        if(tmp=="001") cout<<'1';
        if(tmp=="010") cout<<'2';
        if(tmp=="011") cout<<'3';
        if(tmp=="100") cout<<'4';
        if(tmp=="101") cout<<'5';
        if(tmp=="110") cout<<'6';
        if(tmp=="111") cout<<'7';
    }
    return 0;
}
(4) 八进制转二进制

可以使用“一分三”方法,将八进制数字分为3个二进制数字,点击我见此表0~7项BIN和OCT的关系

#include <iostream>
#include <string>
using namespace std; 
int main() {
    string o; 
    cin >> o; 
    string b; 
    for(int i=0; i<o.length(); i++) {
        if(o[i]=='0') b+="000"; 
        if(o[i]=='1') b+="001"; 
        if(o[i]=='2') b+="010"; 
        if(o[i]=='3') b+="011"; 
        if(o[i]=='4') b+="100"; 
        if(o[i]=='5') b+="101"; 
        if(o[i]=='6') b+="110"; 
        if(o[i]=='7') b+="111"; 
    }
    while(b.length()>1&&b[0]=='0') b.erase(0, 1); //去0
    cout << b; 
    return 0; 
}
(5) 二进制转换为十六进制

使用方法“四合一”,将二进制4个4个地分,点击我见此表0~15项BIN和HEX的关系

#include <bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin>>s;
    if(s=="0"){//排除是0的情况
        cout<<0;
        return 0;
    }
    while(s.length()%4) s="0"+s; //补0
    for(int i=0;i<s.length();i+=4){
        string tmp=s.substr(i,4);
        if(tmp=="0000") cout<<'0';
        if(tmp=="0001") cout<<'1';
        if(tmp=="0010") cout<<'2';
        if(tmp=="0011") cout<<'3';
        if(tmp=="0100") cout<<'4';
        if(tmp=="0101") cout<<'5';
        if(tmp=="0110") cout<<'6';
        if(tmp=="0111") cout<<'7';
        if(tmp=="1000") cout<<'8';
        if(tmp=="1001") cout<<'9';
        if(tmp=="1010") cout<<'A';
        if(tmp=="1011") cout<<'B';
        if(tmp=="1100") cout<<'C';
        if(tmp=="1101") cout<<'D';
        if(tmp=="1110") cout<<'E';
        if(tmp=="1111") cout<<'F';
    }
    return 0;
}
(6) 十六进制转换为二进制

使用方法“一分四”,将十六进制数字分为四个二进制数据点击我见此表0~15项BIN和HEX的关系

#include <bits/stdc++.h>
using namespace std; 
int main() {
    string s, r=""; 
    cin >> s; 
    for(int i=0; i<s.size(); i++) {
        char t=s[i]; 
        if(t=='0') r+="0000"; 
        if(t=='1') r+="0001"; 
        if(t=='2') r+="0010"; 
        if(t=='3') r+="0011"; 
        if(t=='4') r+="0100"; 
        if(t=='5') r+="0101"; 
        if(t=='6') r+="0110"; 
        if(t=='7') r+="0111"; 
        if(t=='8') r+="1000"; 
        if(t=='9') r+="1001"; 
        if(t=='A') r+="1010"; 
        if(t=='B') r+="1011"; 
        if(t=='C') r+="1100"; 
        if(t=='D') r+="1101"; 
        if(t=='E') r+="1110"; 
        if(t=='F') r+="1111"; 
    }
    while(r[0]=='0') r.erase(0, 1); //去0
    if(r.empty()) r="0"; 
    cout << r; 
    return 0; 
}
(7) 八进制转十六进制

我们可以先把八进制转换为二进制,再将二进制转换为十六进制

#include <bits/stdc++.h>
using namespace std; 
int main() {
    string hex, bin, oct; 
    cin >> oct; 
	for(int i=0; i<oct.length(); i++) {//OCT转BIN
		int t = oct[i]; 
		if(t=='0') bin+="000"; 
		if(t=='1') bin+="001"; 
		if(t=='2') bin+="010"; 
		if(t=='3') bin+="011"; 
		if(t=='4') bin+="100"; 
		if(t=='5') bin+="101"; 
		if(t=='6') bin+="110"; 
		if(t=='7') bin+="111"; 
	}
	while(bin.length()%4) bin = "0" + bin; //添0
	for(int i=0; i<bin.length(); i+=4) {//BIN转HEX
		string t = bin.substr(i, 4); 
		if(t=="0000") hex+="0"; 
		if(t=="0001") hex+="1"; 
		if(t=="0010") hex+="2"; 
		if(t=="0011") hex+="3"; 
		if(t=="0100") hex+="4"; 
		if(t=="0101") hex+="5"; 
		if(t=="0110") hex+="6"; 
		if(t=="0111") hex+="7"; 
		if(t=="1000") hex+="8"; 
		if(t=="1001") hex+="9"; 
		if(t=="1010") hex+="A"; 
		if(t=="1011") hex+="B"; 
		if(t=="1100") hex+="C"; 
		if(t=="1101") hex+="D"; 
		if(t=="1110") hex+="E"; 
		if(t=="1111") hex+="F"; 
	}
	while(hex.length()>1&&hex[0]=='0') hex.erase(0, 1); //去0
	if(hex.empty()) hex = "0"; //排除输入0的情况
	cout << hex; 
    return 0; 
}
(8) 十六进制转八进制

一样的,把十六进制转换为二进制,再将二进制转换为十六进制

#include <bits/stdc++.h>
using namespace std; 
int main() {
    string hex, bin, oct; 
    cin >> hex; 
    for(int i=0; i<hex.size(); i++) { //十六进制转二进制 
        char c = hex[i]; 
        if(c=='0') bin += "0000"; 
        if(c=='1') bin += "0001"; 
        if(c=='2') bin += "0010"; 
        if(c=='3') bin += "0011"; 
        if(c=='4') bin += "0100"; 
        if(c=='5') bin += "0101"; 
        if(c=='6') bin += "0110"; 
        if(c=='7') bin += "0111"; 
        if(c=='8') bin += "1000"; 
        if(c=='9') bin += "1001"; 
        if(c=='A') bin += "1010"; 
        if(c=='B') bin += "1011"; 
        if(c=='C') bin += "1100"; 
        if(c=='D') bin += "1101"; 
        if(c=='E') bin += "1110"; 
        if(c=='F') bin += "1111"; 
    }
    while(bin.length()%3) { //补0 
        bin = "0" + bin; 
    }
    for(int i=0; i<bin.length(); i+=3) { //二进制转八进制 
        string t = bin.substr(i, 3); 
        if(t=="000") oct += "0"; 
        if(t=="001") oct += "1"; 
        if(t=="010") oct += "2"; 
        if(t=="011") oct += "3"; 
        if(t=="100") oct += "4"; 
        if(t=="101") oct += "5"; 
        if(t=="110") oct += "6"; 
        if(t=="111") oct += "7"; 
    }
    while(oct.length()>1&&oct[0]=='0') {//去0
        oct.erase(0, 1); 
    }
    if(oct.empty()) oct = "0"; 
    cout << oct; 
    return 0; 

结语

很多伙伴应该都放假了吧,在这里,作者小蛋祝你们暑假快乐\(*^_^*)/
请添加图片描述

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值