Loading

数论——进制

进制

我们平时用的数字都是逢十进一的,称为十进制,逢b进一的计数规则就叫b进制。记作\((Num)_b\)。如\((100110)_2\)为二进制数字100110。b称为基数。

如何转换

我们主要注重任何进制和十进制之间的转换。

b进制展开式

设有一b进制数\((a_k\ a_{k-1}\ a_{k-2}\ ... \ a_0)_b\),下面这个式子可以将它转换成十进制数n。

\[n = a_k\times b^k+a_{k-1}\times b^{k-1} + ... + a_0\times b^0 \]

转换到b进制

把一十进制数n转换成b进制,首先我们要构造这样的式子:

\[n = bq+r \]

这就是上一篇笔记的求余运算嘛,我们得到了两个新的数,商q和余数r。

然后,我们再递归构造上面的式子,把q当作n:

\[q = bq_1 + r_1 \]

直到最后除不下去了,我们把之前的余数反向组合起来,\((r_k\ r_{k-1}\ r_{k-2}\ ...\ r_0)_{b}\)就是结果。

举个例子

\[12345 = 8\times 1543 + 1\\ 1543 = 8\times 192 + 7\\ 192 = 8\times 24 + 0\\ 24 = 8\times 3 + 0\\ 3 = 8\times 0 + 3\\ (12345)_{10} = (30071)_8 \]

n进制转m进制

先思考一个简单的办法,现在我们已经掌握了任意进制到10进制的转换,也掌握了十进制到任意进制的转换,那么对于n,我们可以先把它转换成10进制,再把这个十进制数转换成m进制,不就好了吗。

C++代码

#include "iostream"
#include "string"
#include "cmath"
using namespace std;

int n2t(int src,int base){
	int result = 0;
	int level = 0;
	while(src!=0){
		int x = src%10;
		src = src / 10;
		result += x * pow(base,level++);
	}
	return result;
}

int t2n(int src,int target_base){
	int result = 0;
	int level = 0;
	while(src!=0){
		int mod = src % target_base;
		src = src / target_base;
		result = mod * pow(10,level++) + result;
	}
	return result;
}

int n2m(int src,int base,int target_base){
	if(target_base==10)
		return n2t(src,base);
	else if(base == 10)
		return t2n(src,target_base);
	else{
		return t2n(n2t(src,base),target_base);
	}
}
int main(){
	cout << n2t(120,8) << endl;
	cout << t2n(80,8) << endl;
	cout << n2m(16,8,2) << endl;
	return 0;
}

这段代码只能完成2~10进制的任意转换,因为使用的是int类型,无法表述10进制以上的数了,可以使用字符串解决这个问题。

有没有更简单的办法呢?其实有。

我们常用的进制就是二进制,八进制,十进制,十六进制。对于八进制,因为\(8=2^3\),所以1位八进制数可以完整的用3位二进制来表示,这样就可以建立一对一关系。而十六进制也是一样的,1位十六进制可以完整的用4位二进制来表示。

二进制 八进制 十六进制
000 0 0
001 1 1
010 2 2
011 3 3
100 4 4
101 5 5
110 6 6
111 7 7
1000 10 8
1001 11 9
1010 12 A
1011 13 B
1100 14 C
1101 15 D
1110 16 E
1111 17 F

我们几个八进制来举例,比如\((12)_8\),我们先查\((1)_8\),发现\((1)_8=(001)_2\),然后查\((2)_8=(010)_2\),所以\((12)_8\)就是把每个八进制位对应的二进制数简单的做字符串相加即可得到\((12)_8=(001010)_2\),去除前面的00,查表发现结果是正确的。十六进制也是一样,不演示了。

所以有了这个理论基础,对于二的幂次作为基数的进制,我们可以直接建立一个表,让计算机去查表,这样就可以更快的完成运算。

伪代码

h2b_table = {0->0000,1->0001,...,F->1111}
function h2b(hexString): string
    result = ""
    for each char c in hexString
        result += h2b_table[c];
    return removeFrontSpace(result)
posted @ 2020-10-04 20:11  yudoge  阅读(536)  评论(0编辑  收藏  举报