进制
进制
$\texttt{SeekLuna}$ $2023.6.18$
概念
数量是抽象的,用物体、符号代替数量(结绳计数,算盘,正字计数)
阿拉伯数字符号$0-9$,我们畅通阿拉伯数字来表示数量。
进制
进制:按照一定比例对符号进行换算。
基数:进制数,可以使用的不同的符号的数量。
位
数量是无限的,不能用无限的符号来表示数量,而摆放符号的位置是无限的,这些位置就被称为位。
书写规范:左边为高位,右边位低位。整数部分最低位编号为0,忽略前缀0;小数部分最高位编号为-1,忽略后缀0。
例题:数位取出
给定一个整数 $n$(十进制下),求它在 $a$ 进制表示下 $b$ 号位上的数。
我们只需给$n$除以$b$次$a$,再$\bmod a$,就可以得出$b$号位上的数
$\text{Code:}$
#include<bits/stdc++.h>
using namespace std;
int n, a, b;
int main(){
cin >> n >> a >> b;
for (int i = 1; i <= b; i++){
n /= a;
}
cout << n % a;
return 0;
}
位权:当前位的$1$与$0$号位的1之间的换算比例,$i$号位的位权为基数的$i$次方。可以理解为每个位置对应的单位值。
以十进制为例:
| 位号 | $2$ | $1$ | $0$ | $1$ |
|---|---|---|---|---|
| 位权 | $10_{} ^ {2} = 100$ | $10_{} ^ {1} = 10$ | $10_{} ^ {0} = 1$ | $10_{} ^ {-1} = 0.1$ |
| 符号 | 4 | 5 | 6 | 7 |
数值为:$4 \cdot 10_{} ^ {2}+5 \cdot 10_{} ^ {1} + 6 \cdot 10_{} ^ {0} + 7 \cdot 10_{} ^ {-1} = 456.7$,其中$a_{} ^ {-b} = \frac{1}{a_{} ^ {b}}$,并且乘幂运算有性质$a_{} ^ {b} \cdot a_{} ^ {c} = a_{} ^ {b+c}$
例题:数位修改
给定一个正整数$n$(十进制下),将它的$n$进制表示中的$n$号位修改成$x$,再用十进制进行输出。
我们只需要求出$b$号位的位权,然后将$n$加上这个位权,就可以了。
$\text{Code:}$
#include<bits/stdc++.h>
using namespace std;
int n,a,b,x;
int main(){
cin >> n >> a >> b >> x;
long long t = 1;
int y = n;
for (int i = 1; i <= b; i++){
t *= a;
y /= a;
}
y %= a;
cout << n + (x - y) * t;
return 0;
}
进制表示
最简表示:每一位上的符号只有一个
从低位换算到相邻高位,称为进位。从高位换算到相邻低位,称为借位。高位的1等价于相邻低位的基数。
对于非最简表示,每一位上有多个符号,需要通过进位,借位将其转为最简表示。
| 位号 | 2 | 1 | 0 | 数值 |
|---|---|---|---|---|
| 位权 | $10_{} ^ {2} = 100$ | $10_{} ^ {1} = 10$ | $10_{} ^ {0} = 1$ | |
| 最简表示 | 4 | 5 | 6 | $4 \cdot 10_{} ^ {2} + 5 \cdot 10_{} ^ {1} + 6 \cdot 10_{} ^ {0} = 456$ |
| 其他表示1 | 2 | 25 | 6 | $2 \cdot 10_{} ^ {2} + 25 \cdot 10_{} ^ {1} + 6 \cdot 10_{} ^ {0} = 456$ |
| 其他表示2 | 1 | 28 | 76 | $1 \cdot 10_{} ^ {2} + 28 \cdot 10_{} ^ {1} + 76 \cdot 10_{} ^ {0} = 456$ |
| 当基数很大时,每一位上有多个符号,只要他小于基数,就是最简表示。例如一个$92$进制数的最简表示: | 位号 | 2 | 1 | 0 |
|---|---|---|---|---|
| 位权 | $92_{} ^ {2} = 8464$ | $92_{} ^ {1} = 92$ | $92_{} ^ {0} = 1$ | |
| 符号 | 27 | 91 | 35 |
其数值为$27 \cdot 92_{} ^ {2}+91 \cdot 92_{} ^ {1}+35 \cdot 92_{} ^ {0} = 236935$
以下为$1-31$的10、2、16进制表
| 十进制 | 二进制 | 十六进制 |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 10 | 2 |
| 3 | 11 | 3 |
| 4 | 100 | 4 |
| 5 | 101 | 5 |
| 6 | 110 | 6 |
| 7 | 111 | 7 |
| 8 | 1000 | 8 |
| 9 | 1001 | 9 |
| 10 | 1010 | 0A |
| 11 | 1011 | 0B |
| 12 | 1100 | 0C |
| 13 | 1101 | 0D |
| 14 | 1110 | 0E |
| 15 | 1111 | 0F |
| 16 | 10000 | 10 |
| 17 | 10001 | 11 |
| 18 | 10010 | 12 |
| 19 | 10011 | 13 |
| 20 | 10100 | 14 |
| 21 | 10101 | 15 |
| 22 | 10110 | 16 |
| 23 | 10111 | 17 |
| 24 | 11000 | 18 |
| 25 | 11001 | 19 |
| 26 | 11010 | 1A |
| 27 | 11011 | 1B |
| 28 | 11100 | 1C |
| 29 | 11101 | 1D |
| 30 | 11110 | 1E |
| 31 | 11111 | 1F |
基数运算
-
乘以基数,相当于在对应进制下左移一位;
-
除以基数,相当于在对应进制下右移一位;
-
对基数取模,相当于取出$0$号位上的数。
进制转换
$10$进制转$k$进制通常使用乘除法,$k$进制转$10$进制通常使用位值累加法。
$10$进制转$k$进制通常对数值转数字串,$k$进制转$10$进制。
$a$进制转$b$进制,通常先将$a$进制转为$10$进制,然后再转为$b$进制。
位值累加法
每一位上的数字乘上当前进制的位权并累加。
$2$进制转$10$进制:
$(1101.11)_{2} = 1 \cdot 2_{} ^ {3}+1 \cdot 2_{} ^ {2}+0 \cdot 2_{} ^ {1}+1 \cdot 2_{} ^ {1}+1 \cdot 2_{} ^ {-1}+1 \cdot 2_{} ^ {-2}=13.75$
例题:$x$ 进制转 10 进制($\texttt{Luogu}$有)
给定一个小整数 $x$ 和一个 $x$ 进制的数 $S$。将 $S$ 转为 $10$ 进制数。对于超过十进制的数码,用A,B,$\dots$表示。
我们可以用位值累加法。
$\text{Code:}$
#include<bits/stdc++.h>
using namespace std;
int k,ans;
string s;
int main(){
cin >> k >> s;
int len = s.size();
for (int i = 0; i < len; i++){
ans = ans * k + (s[i] <= '9' ? s[i] - '0' : s[i] - 'A' + 10);
}
cout << ans;
return 0;
}
乘除法
将每一位移动到0号位取出。
- 使用除法,除以目标进制基数,由高到低求出整数部分;
-
使用乘法,乘以目标进制基数,由低到高求出小数部分。
$10$进制转$16$进制:$(1234)_{10}=(4D2)_{16}$
例题:x 进制转 10 进制
给一个小整数 $x$ 和一个 $x$ 进制的数 $S$。将 $S$ 转为 $10$ 进制数。对于超过十进制的数码,用A,B$\dots$表示。
我们可以用乘除法。
$\text{Code:}$
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 32;
int n,x,tot,a[MAXN];
int main(){
cin >> n >> x;
for (;n > 0;){
a[tot++] = n % x;
n /= x;
}
for (int i = tot - 1; i >= 0; i--){
cout << char(a[i] <= 9 ? a[i] + '0' : a[i] - 10 + 'A');
}
return 0;
}

浙公网安备 33010602011771号