进制

进制

$\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;
}

完结撒花!

posted @ 2023-06-20 18:44  rksm2333  阅读(37)  评论(0)    收藏  举报  来源