马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 zhangjinxuan 于 2022-8-31 19:53 编辑
在开始之前,请让我啰嗦两句什么是进制(明白的鱼油跳到1的位置)
进制也就是进位计数制,是人为定义的带进位的计数方法(有不带进位的计数方法,比如原始的结绳计数法,唱票时常用的“正”字计数法,以及类似的tally mark计数)。 对于任何一种进制---X进制,就表示每一位上的数运算时都是逢X进一位。 十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位(这么专业的语言,肯定不是我写的 )
可能还有的鱼油很懵逼,专业的语言听不懂!那用我的话说吧:
进制决定了一个数能表示哪些数字,比如10进制,可以表示0~9的数字,如果要表示更大的数字那就要进位 比如:9+2=11。
换个例子,比如8进制,可以表示0~7的数字,要表示更大的数同样要进位,比如6+2在8进制中不能等于8,应向前进一,最后6+2在八进制中等于10。
进制的表示方法很简单,比如一个b进制数x,表示为(x)b(应在数字两边打括号,再把进制写在右括号的右下角),比如2进制数1010,表示为(1010)2
常用的进制有:2进制,8进制,10进制(这就是我们刷数学题用的进制),16进制,有人可能会说:我们10进制用的好好的,干嘛要发明2,8,16进制让我们快乐学习呢?
其实计算机很'2',它只能表示0,1,就是二进制,计算机的地址使用16进制表示的,C++/C也可以用8进制表示数字。为什么8,16进制与计算机关系这么密切?
因为计算机很‘2’,它喜欢和2有关的,8正好就是2的3次方,16正好是2的4次方,所以,学习进制还是很重要的。
回归正题,我们来学学怎么实现不同进制间的转换吧!
1. X进制转10进制:
用的是按位展开求和的方法,什么意思呢?想一想我们可以怎样表示一个10进制数
比如(34201)10 怎么表示?聪明的鱼油会这么表示:34201=3*10000+4*1000+2*100+0*10+1
对,这么表示正确,但不够一目了然,可以这么表示:34201=3*10^4 + 4*10^3 + 2*10^2 + 0*10^1 +1*10^0 (^为求幂)
可能聪明的鱼油明白按位展开求和是什么意思了,所以我们看看是不是对2进制,或别的进制有效:
(10)2=1*2^1+0*2^0=(2)10 检验一下:2在10进制中等于1+1,而1+1在2进制中就是(10)2
可能还是有的鱼油很懵,没事,很正常,我们来看几个例子:
(1101)2=1*2^3+1*2^2+0*2^1+1*2^0=8+4+1=(13)10
(235)8=2*8^2+3*8^1+5*8^0=128+24+5=(157)10
(404)5=4*5^2+0*5^1+4*5^0=100+0+4=(121)10
(ABC)16 我的天哪,ABC是什么鬼?其实上,为了表示16进制或更多的进制的数,就只能用英文字母表示了(可用大写、小写,我喜欢用大写)
A对应的是10,B对应的是11,C对应的是12,D对应的是13,E->14,F->15,......
所以不难计算出(ABC)16=10*16^2+11*16^1+12*16^0=2560+176+12=(2748)10
小数怎么转换呢?同样也是按位展开求和,但得是负数,比如这样:
(0.22)3=2*3^-1+2*3^-2≈(0.889)10
整数部分与小数部分分开转换,最后加起来就可以了!
有的人又说3^-1我不会算!其实很简单:不看负号,算3^1=3,最后求出倒数就可以了(x的倒数是1/x)
举个例子(13A.B3A)16=1*16^2+3*16^1+10*16^0+11*16^-1+3*16^-2+10*16^-3=(314.70166015625)10
讲了这么多,相信大家都会了,现在,上代码!#include <bits/stdc++.h>
using namespace std;
int pp(string number) //返回number中点号的位置
{
int len=number.size();
for (int i=0;i<len;++i)
if (number[i]=='.')
return i;
return len;
}
double p1(string number,int base)
{
double res=0;
int len=number.size(),ppos=pp(number),t=1;
for (int p=ppos-1;p>=0;--p) //整数转换--从左往右看
{
res+=(number[p]>='A'?number[p]-'A'+10:number[p]-'0')*t;
t*=base;
}
if (ppos==len)return res;
else
{
double t=base;
for(int p=ppos+1,i=-1;p<len;++p,--i)//小数转换--从右往左看
{
res+=(number[p]>='A'?number[p]-'A'+10:number[p]-'0')*(1/t);//倒数
t*=base;
}
return res;
}
}
int main()
{
string number;
int base;
cin>>number>>base;
printf("%g",p1(number,base));
}
2. 10进制转x进制:
使用除x取余法,什么意思呢?就是不停把除x的余数保存,再/=x,我们看个例子:
12转为2进制是多少?
step 1: 12/2=6 余数为 0
step 2: 6/2=3 余数为 0
step 3: 3/2=1 余数为 1
step 4: 1/2=0 余数为 1
step 5: 结果已为0,无需进行计算,最后答案倒序输出
所以 (12)10=(1100)2
这就是除x取整法,比按位展开求和算起来简单许多
再看个例子:
6666转16进制是多少?
step 1:6666/16=416 余数为 10
step 2:416/16=26 余数为 0
step 3:26/16=1 余数为 10
step 4:1/16=0 余数为 1
step 5:结果已为9,无需进行计算,最后答案倒序输出,注:大于等于10的数字要转换成英文字母,比如10转换为A,11转换为B,14转换为E
所以(6666)10=(1A0A)16
[大家扣一波 1A0A]
对于小数,那就用乘x(代表进制)取整法,这是啥意思啊 ,就是乘一次x,把结果的整数部分保存,把整数部分变为零,直到x变为0, 我们举个栗子:
0.125转为2进制是多少?
step 1:0.125*2=0.25 整数部分为 0
step 2:0.25*2=0.5 整数部分为 0
step 3:0.5*2=1 整数部分为 1,然后把整数部分变为0(每乘一次记录整数部分,再把整数部分变为0,然后继续乘)
step 4:如果结果变成0,就不除了,最后按顺序输出
所以(0.125)10=(0.001)2
注:不一定所有的数都能转换,有时候会转换成无限小数,大家可以试一试0.3转2进制
再看个例子,加深大家的理解:
0.32转8进制约是多少?
step 1: 0.32*8=2.56 整数部分为 2
step 2: 0.56*8=4.48 整数部分为 4
step 3: 0.48*8=3.84 整数部分为 3
step 4: 0.84*8=6.72 整数部分为 6
step 5: 0.72*8=5.76 整数部分为 5
...
所以(0.32)10≈(0.24365)8
大多数字转换别的进制数都会变为无限小数,所以一般算6位左右就差不多了
如果对于既有整数又有小数的数字,比如31.41转8进制,分开转换再相加即可。
上代码加深鱼油们的理解:#include <bits/stdc++.h>
using namespace std;
string ip2(int number,int base,string res) //整数部分的转换,因为是逆序输出,所以我想到了栈,因为我想到了栈,所以我想到了递归
{
if (number<base)return char(number>9?number-10+'A':number+'0')+res;
return ip2(number/base,base,char(number%base>9?number%base-10+'A':number%base+'0')+res); //仔细回想方法,读完这句并不难
}
string fp2(double number,int base) //小数转换,这就没必要用递归了
{
int c=0;//为防止死循环,定义一个c变量
string res;
while (number && c!=50)//最多保留50位小数
{
number*=base;//乘x
res=res+char(int(number)>9?number-10+'A':number+'0');//取整
++c;
number=number-int(number);//保留小数
}
return res;
}
string p2(double number,int base)
{
string tmp = ip2(int(number),base,"");
if (int(number)!=number)tmp=tmp+"."+fp2(number-int(number),base);
return tmp;
}
int main()
{
double x;
int base;
scanf("%lf%d",&x,&base);
cout<<p2(x,base);
}
实际上,在C++中,有10进制转X进制的函数,那就是atoi,但只能进行整数的转换
用法:#include <bits/stdc++.h>
using namespace std;
int main()
{
char res[100];
atoi(6666,res,16);
printf("%s",res);
}
程序输出:
1a0a
3 x进制数a 转y进制
虽然很简单,但算起来特别难
方法:把a转换为10进制数b,用按位展开求和的方法,然后把b转换为y进制,用除x取整/乘x取整的方法。
比如(1010)2转8进制:
先转10进制:1*2^3+1*2**1=8+2=10
再转8进制:
10/8=1 余2
1/8=0 余1
结果为12,代码很简单,可以自己写^_^
4.不同进制间的运算
先一起转10进制,接着按要求进行运算,再转为要求的进制
5.广告:求评分回帖加顶 !
[本文为本萌新原创,仅学习使用,若有不正请大佬指正,有YB!] |