文章目录
进位计数法
r r r进制进位计数法
进位计数法(Positional Notation or Place-Value Notation)是一种使用固定的基数(base)来表示数值的方法。
进位计数法中,数位(位数)越靠左,表示的数值越大。
常见的进位计数法有二进制、十进制、十六进制等。
基本概念
-
基数(Base or Radix)
进位计数法的基数是指每位上可以使用的符号数量。常见的基数包括:- 二进制(Binary),基数为2,符号为0和1。
- 十进制(Decimal),基数为10,符号为0到9。
- 十六进制(Hexadecimal),基数为16,符号为0到9和A到F(其中A表示10,B表示11,依此类推)。
-
权值(Place Value or Weight)
在进位计数法中,每一位上的数值都有一个权值,权值由基数和该数位的位置共同决定。通常,权值随着数位的增高而增大。例如:- 在十进制中,数值123的权值可以表示为: 1 × 1 0 2 + 2 × 1 0 1 + 3 × 1 0 0 = 123 1 \times 10^2 + 2 \times 10^1 + 3 \times 10^0 = 123 1×102+2×101+3×100=123。
- 在二进制中,数值1011的权值表示为: 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 1 × 2 0 = 11 1 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 1 \times 2^0 = 11 1×23+0×22+1×21+1×20=11。
-
进位(Carrying)
当一个数位上的数字达到基数时,就会进位。例如:- 十进制中,9之后再加1就会变成10,这时个位清零并向十位进1。
- 二进制中,1之后再加1就会变成10,即个位清零并向更高位进1。
常见的进位计数法
进位计数法 | 基数 | 符号 | 示例 |
---|---|---|---|
二进制 | 2 | 0, 1 | 101 1 2 = 1 1 10 1011_2 = 11_{10} 10112=1110 |
八进制 | 8 | 0–7 | 1 7 8 = 1 5 10 17_8 = 15_{10} 178=1510 |
十进制 | 10 | 0–9 | 12 3 10 = 12 3 10 123_{10} = 123_{10} 12310=12310 |
十六进制 | 16 | 0–9, A–F | 1 A 16 = 2 6 10 1A_{16} = 26_{10} 1A16=2610 |
进位计数法的应用
-
计算机科学
计算机系统中广泛使用二进制,因为硬件电路只需要两种状态(0和1)来表示信息。此外,十六进制和八进制常用于简化表示二进制数。 -
日常生活
十进制是最常用的进制体系,符合人类直观的计数习惯。小时计时(24小时制)和角度测量(60进制)也可以看作特殊的进位计数法应用。 -
编码系统
各种编码系统(如颜色编码、字符编码)常使用不同进制进行表示,以便于识别和计算。例如,在RGB颜色编码中,常使用十六进制表示每种颜色的强度。
相关概念
- 进位计数法中,每个数位用到的不同数码的个数称为基数
-
十进制的基数radix=10
- 包括0~9
- 每个数位计满10,就向高位进1(逢十进一)
- 不同数位上的数码所代表(对应)的常数(权)称为位权
-
一个进位数的数值大小就是它的各位数码按权相加
-
r进制数
设某个 r r r 进制数 S r = ( K n K n − 1 ⋯ K 0 K − 1 ⋯ K − m ) S_r = (K_nK_{n-1}\cdots{K_0}K_{-1}\cdots{K_{-m}}) Sr=(KnKn−1⋯K0K−1⋯K−m),这个 r r r进制数整数部分有 n + 1 n+1 n+1位,小数部分有 m m m位
-
以十进制为例, 321.123 321.123 321.123中, K 2 , K 1 , K 0 K_{2},K_{1},K_{0} K2,K1,K0分被为 3 , 2 , 1 3,2,1 3,2,1;而 K − 1 , K − 2 , k − 3 K_{-1},K_{-2},k_{-3} K−1,K−2,k−3分被为 1 , 2 , 3 1,2,3 1,2,3;
- 按照上述的 S r S_{r} Sr表示式,数码 K i K_{i} Ki数对应的位权将恰好为 r i r^{i} ri;注意 K i K_{i} Ki是整数部分 K n ⋯ K 0 K_{n}\cdots{K_{0}} Kn⋯K0的从低位到高位数的第 i + 1 i+1 i+1位,而不是第 i i i位
- 例如,在 321.123 321.123 321.123中最高位的权如何确定?只需要从次高位开始数到整数部分的最后一位,假设数出来的数码共有 i i i位,那么最高位的权就是 r i r^{i} ri;
- 这个方法是通用的,对于非最高位数字的位权的确定,方法完全一样(假设数码 K i K_{i} Ki需要确定它对应的权,那么比 K i K_{i} Ki高位的部分就不用看了,只需把 K i K_{i} Ki看成最高位,然后数到最后一位整数位即可)
- 再举个例子,二进制数1001的最高位权是多少?( 2 3 2^{3} 23=8)
-
K i K_i Ki 表示数位 i i i 上的数码,由于 S r S_{r} Sr是一个 r r r进制数, r r r进制数的有 r r r个数码,他们分别是 0 , 1 , ⋯ , r − 1 {0,1,\cdots,{r-1}} 0,1,⋯,r−1, K i ∈ { 0 , ⋯ , r − 1 } K_i \in \set{0,\cdots ,r-1} Ki∈{0,⋯,r−1}, i ∈ [ − m , n ] i \in [-m, n] i∈[−m,n], i ∈ Z i\in\mathbb{Z} i∈Z
- 例如,十进制数 S 10 S_{10} S10,数码(单位(一位或个位)整数)的可能取值为 0 , 1 , ⋯ , 9 0,1,\cdots,9 0,1,⋯,9,注意取不到10,这已经是两位数了
-
从高位权向低位权数码书写; S r S_r Sr 是一个含有 n + 1 + m n + 1 + m n+1+m 位数码的数。
-
其大小可以用它的按权相加: ∑ i = n − m K i r i \sum_{i=n}^{-m} K_i r^i ∑i=n−mKiri来衡量。
-
r i = r i r_i=r^{i} ri=ri 是 K i K_i Ki 的位权。
除法相关概念
进制转换中会用到除法,带余除法等操作;
在一个除法算式里,被除数、余数、除数和商(Quotient)的关系有以下三种等价描述
- (被除数-余数)÷除数=商
- 被除数÷除数=商··· ···余数。
- 被除数=商×除数+余数(带余除法形式)
上述式子从不同角度给出了商的含义,
这里主要明确一点, a / b a/b a/b的结果可能不是整数,如果结果不是整数,那么 a / b a/b a/b不能称为 a ÷ b a\div{b} a÷b的商,商一定是整数,除不尽时用非零余数表示
带有余数的情况:
- 被除数÷除数=商……余数(其中,余数小于除数)
- 除数×商+余数=被除数。
考虑到除法与乘法互为逆运算,并且乘法的意义是求多个相同加数的和的简便运算,
除法这种情况也可以解释为:被除数不断地减去除数,直至余数数值低于除数。例如:17÷5=3…2,
完全商和不完全商
当数a除以数b(非0)能除得尽时,这时的商叫完全商。如:9÷3=3,3就是完全商。
如果数a除以数b(非0)除不尽,得到的商就是不完全商。如:10÷3=3…1,这里的3就是不完全商。
不同进制数间的转换
- 进制数转换需要分别考虑整数部分和小数部分
- 整数部分:从低位到高位
- 小数部分:从高位到低位
- 整数转换用的比较多,重点掌握,在数论的带余除法相关理论也介绍了转换方法
- 专业选手也要对小数部分的转换熟练
2进制转2的幂进制( 2 k 2^k 2k)
整数部分和小数部分一起介绍转换
-
8进制:3个二进制代码一组( 2 3 = 8 2^3=8 23=8)
-
16进制:4个二进制代码一组( 2 4 = 16 2^4=16 24=16)
-
…类推:
- 2进制转为 r = 2 k r=2^k r=2k进制:以 k = log 2 r = log 2 2 k k=\log_2{r}=\log_2{2^k} k=log2r=log22k个按 2 → 2 k 2\to{2^k} 2→2k顺序规则,将二进制代码以每 k k k个一组,分组转换为 2 k 2^k 2k进制
- 如果遇到某个组内的数码位数
p
p
p不够
k
k
k个
(
p
<
k
)
(p<k)
(p<k),那么
- 这种组只会发生在整数部分最高位所在的组或者小数部分最低位所在的组
- 在边缘(外沿)补0,凑满k个,然后转换
- 这种转换关系的理论基础是按权展开,以
10011001
这个8位二进制数为例,将它转换为16进制,那么对于安全展开: ( 1 × 2 7 + 0 × 2 6 + 0 × 2 5 + 1 × 2 4 ) (1\times{2^{7}}+0\times{2^{6}}+0\times{2^{5}}+1\times{2^{4}}) (1×27+0×26+0×25+1×24)+ ( 1 × 2 3 + 0 × 2 2 + 0 × 2 1 + 1 × 2 0 ) (1\times{2^{3}}+0\times{2^{2}}+0\times{2^{1}}+1\times{2^{0}}) (1×23+0×22+0×21+1×20)= ( 1 × 2 3 + 1 ) × 2 4 (1\times 2^{3}+1)\times{2^{4}} (1×23+1)×24+ ( 1 × 2 3 + 0 × 2 2 + 0 × 2 1 + 1 ) × 2 0 (1\times{2^{3}}+0\times{2^{2}}+0\times{2^{1}}+1)\times{2^{0}} (1×23+0×22+0×21+1)×20= 9 × 2 4 + 9 × 2 0 9\times{2^{4}}+9\times{2^{0}} 9×24+9×20= 9 × 1 6 1 + 9 × 1 6 0 9\times{16^{1}}+9\times{16^{0}} 9×161+9×160;由此可见 1001100 1 2 10011001_{2} 100110012= 9 9 16 99_{16} 9916
-
更一般的,我们有基于按权展开关系式
-
∑
j
=
p
i
p
i
+
(
p
−
1
)
K
j
r
j
\sum_{j=pi}^{pi+(p-1)}K_{j}r^{j}
∑j=pipi+(p−1)Kjrj=
r
p
i
∑
j
=
p
i
p
i
+
(
p
−
1
)
K
j
r
j
−
p
i
r^{pi}\sum_{j=pi}^{pi+(p-1)}K_{j}r^{j-pi}
rpi∑j=pipi+(p−1)Kjrj−pi=
r
p
i
(
K
p
i
r
0
+
K
p
i
+
1
r
1
+
⋯
+
K
p
i
+
(
p
−
1
)
r
p
−
1
)
r^{pi}(K_{pi}r^{0}+K_{pi+1}r^{1}+\cdots+K_{pi+(p-1)}r^{p-1})
rpi(Kpir0+Kpi+1r1+⋯+Kpi+(p−1)rp−1),
i
=
0
,
1
,
2
,
⋯
,
⌊
n
/
p
⌋
i=0,1,2,\cdots,\lfloor{n/p}\rfloor
i=0,1,2,⋯,⌊n/p⌋;
- 这个关系式揭示了 r r r进制转为 r p r^{p} rp进制时,可以 p p p个一组进行转化
- 回到2进制转为 2 4 2^{4} 24= 16 16 16进制的问题上来,令 r = 2 r=2 r=2, p = 4 p=4 p=4
- 则 K 4 i + 3 . . K 4 i K_{4i+3}..K_{4i} K4i+3..K4i这部分对应的到按权展开为 ∑ j = 4 i 4 i + 3 K j 2 j \sum_{j=4i}^{4i+3}K_{j}2^{j} ∑j=4i4i+3Kj2j= 2 4 i ∑ j = 4 i 4 i + 3 K j 2 j − 4 i 2^{4i}\sum_{j=4i}^{4i+3}K_{j}2^{j-4i} 24i∑j=4i4i+3Kj2j−4i= ( 2 4 ) i ( K 4 i 2 0 + K 4 i + 1 2 1 + K 4 i + 2 2 2 + K 4 i + 3 2 3 ) (2^{4})^{i}(K_{4i}2^{0}+K_{4i+1}2^{1}+K_{4i+2}2^{2}+K_{4i+3}2^{3}) (24)i(K4i20+K4i+121+K4i+222+K4i+323)
-
∑
j
=
p
i
p
i
+
(
p
−
1
)
K
j
r
j
\sum_{j=pi}^{pi+(p-1)}K_{j}r^{j}
∑j=pipi+(p−1)Kjrj=
r
p
i
∑
j
=
p
i
p
i
+
(
p
−
1
)
K
j
r
j
−
p
i
r^{pi}\sum_{j=pi}^{pi+(p-1)}K_{j}r^{j-pi}
rpi∑j=pipi+(p−1)Kjrj−pi=
r
p
i
(
K
p
i
r
0
+
K
p
i
+
1
r
1
+
⋯
+
K
p
i
+
(
p
−
1
)
r
p
−
1
)
r^{pi}(K_{pi}r^{0}+K_{pi+1}r^{1}+\cdots+K_{pi+(p-1)}r^{p-1})
rpi(Kpir0+Kpi+1r1+⋯+Kpi+(p−1)rp−1),
i
=
0
,
1
,
2
,
⋯
,
⌊
n
/
p
⌋
i=0,1,2,\cdots,\lfloor{n/p}\rfloor
i=0,1,2,⋯,⌊n/p⌋;
-
对于小数部分,我们有完全相仿的结论
例
以8进制为例
- 例如
S
(
2
)
=
1111000010.01101
S_{(2)}=1111000010.01101
S(2)=1111000010.01101
- ( 00 ‾ 1 ) ( 111 ) ( 000 ) ( 010 ) . ( 011 ) ( 01 0 ‾ ) (\underline{00}1)(111)(000)(010).(011)(01\underline{0}) (001)(111)(000)(010).(011)(010)= 1702.3 2 8 1702.32_{8} 1702.328这里首尾两组有不足3位数的情况,所以分别补0,然后各自转换为8进制数码
- ( 0011 ) ( 1100 ) ( 0010 ) . ( 0110 ) ( 1000 ) = 3 C 2.6 8 16 (\mathbb{00}11)(1100)(0010).(0110)(1\mathbb{000})=3C2.68_{16} (0011)(1100)(0010).(0110)(1000)=3C2.6816
2的幂进制 ( 2 k ) (2^{k}) (2k)转2进制
- 按照上述规则反方向操作即可:
- 2 k 2^k 2k进制转2进制,将 S 2 k S_{2^k} S2k的每一位数码都转换为k位2进制代码
- 每个数码转换的二进制代码中,高位缺失的补0,直到补满k位为止
- 最后,在修剪两侧边缘的0即可
通用转换理论知识👺
- 假设一个 r 1 r_1 r1进制数 S r 1 S_{r_1} Sr1要被转换为 r r r进制的形式 S r S_{r} Sr,我们要怎么做?
- 不放蛇 S r 1 S_{r_1} Sr1转换为 r r r进制 S r S_{r} Sr的各个数码为 K n ⋯ K 0 . K − 1 K − 2 ⋯ K − m K_{n}\cdots{K_{0}}.K_{-1}K_{-2}\cdots{K_{-m}} Kn⋯K0.K−1K−2⋯K−m,这里的 m m m可能是无穷的(即便 S r 1 S_{r_1} Sr1的小数是有尽的)
- 现在问题就转换为如何确定 S r 1 S_{r_1} Sr1转为 S r S_{r} Sr后的 K i K_{i} Ki ( i = − m , ⋯ , − 1 , 0 , 1 , ⋯ , n ) (i=-m,\cdots,-1,0,1,\cdots,n) (i=−m,⋯,−1,0,1,⋯,n)
如果我们将 S r S_r Sr整数部分和小数部分分别截取出来:
-
整数部分
Z = K n r n + K n − 1 r n − 1 + ⋯ + K 1 r 1 + K 0 = ∑ i = 0 n K n − i r n − i = ∑ i = 0 n K i r i ; K i ∈ [ 0 , r ] Z=K_{n} r^{n}+K_{n-1} r^{n-1}+\cdots+K_{1}r^{1}+K_{0} =\sum_{i=0}^{n}K_{n-i}r^{n-i} =\sum_{i=0}^{n}K_{i}r^{i};K_i\in[0,r] Z=Knrn+Kn−1rn−1+⋯+K1r1+K0=i=0∑nKn−irn−i=i=0∑nKiri;Ki∈[0,r] -
小数部分
D = ∑ i = − m − 1 K i r i = ∑ i = 1 m K − i r − i D=\sum\limits_{i=-m}^{-1}K_ir^{i}=\sum\limits_{i=1}^{m}K_{-i}r^{-i} D=i=−m∑−1Kiri=i=1∑mK−ir−i
整数部分
-
令 Z 0 Z_0 Z0= Z Z Z,则有 Z 1 Z_1 Z1= [ Z 0 / r ] [Z_{0}/r] [Z0/r]= K n r n − 1 + K n − 1 r n − 2 + ⋯ + K 1 K_{n} r^{n-1}+K_{n-1} r^{n-2}+\cdots+K_{1} Knrn−1+Kn−1rn−2+⋯+K1(余数为 K 0 K_{0} K0),
-
Z i + 1 = [ Z i / r ] Z_{i+1}=[Z_{i}/r] Zi+1=[Zi/r], ( i = 0 , 1 , 2... , n ) (i=0,1,2...,n) (i=0,1,2...,n), Z i / r Z_{i}/r Zi/r相当于 Z i Z_{i} Zi小数点向左移动一位,
- Z i Z_{i} Zi= K n ⋯ K i K_{n}\cdots{K_{i}} Kn⋯Ki, Z i / r = K n ⋯ K i + 1 . K i Z_{i}/r=K_{n}\cdots{K_{i+1}.K_{i}} Zi/r=Kn⋯Ki+1.Ki;
- 并且 Z i % r Z_{i}\%{r} Zi%r= K i K_{i} Ki
-
这里约定 [ ] [\ ] [ ]符号为取整号,小数部分丢弃仅保留整数,这种情况下,可以保证 Z i Z_{i} Zi是整数 ( K i < r ) (K_{i}<r) (Ki<r)
- Z 0 % r = K 0 Z_{0}\%r=K_{0} Z0%r=K0
- Z 1 % r = K 1 Z_{1}\%r=K_{1} Z1%r=K1
- …
- Z i % r = K i Z_{i}\%{r}=K_{i} Zi%r=Ki
- …
- Z n % r = K n Z_{n}\%{r}=K_{n} Zn%r=Kn
-
可以看到,这个过程是从低位开始往高位计算的
- 程序设计的时候可以利用递归的方式代替循环来从高位往低位输出
-
如果数 S r S_{r} Sr整数部分有 n + 1 n+1 n+1位,那么需要计算 n + 1 n+1 n+1次来依次得到 K 0 , K 1 , ⋯ , K n K_{0},K_{1},\cdots,{K_{n}} K0,K1,⋯,Kn
-
当计算到最高位 K n K_{n} Kn时, Z n / r = 0 Z_{n}/r_{}=0 Zn/r=0,
-
-
上述方案是递推方案,也可以用通项方案:
- K i K_{i} Ki= [ Z / r i ] % r [Z/r^{i}]\%{r} [Z/ri]%r
-
根据上述讨论,被转换的数的整数部分不断的做除基取余操作,最终总是能够将最高位数码确定下来
小数部分
-
大体类似,但是要略微复杂一些,因为涉及到精度损失,并且操作时将从高位往低位求出
-
计算小数部分的数码顺序为 K − 1 , K − 2 , ⋯ , K − m K_{-1},K_{-2},\cdots,K_{-m} K−1,K−2,⋯,K−m
-
令 R 1 = D R_1=D R1=D= 0. K − 1 K − 2 ⋯ K − m 0.K_{-1}K_{-2}\cdots{K_{-m}} 0.K−1K−2⋯K−m,约定符号 [ x ] [x] [x]表示取 x x x的整数部分
-
K − 1 K_{-1} K−1= [ R 1 / r − 1 ] [R_1/r^{-1}] [R1/r−1]= [ R 1 r ] [R_{1}r] [R1r]= [ ∑ i = 1 m K − i r 1 − i ] [\sum\limits_{i=1}^{m}K_{-i}r^{1-i}] [i=1∑mK−ir1−i]= [ K − 1 + ∑ i = 2 m K − i r 1 − i ] [K_{-1}+\sum_{i=2}^{m}K_{-i}r^{1-i}] [K−1+∑i=2mK−ir1−i],取其整数部分 K − 1 K_{-1} K−1,
- 剩余部分 R 2 R_{2} R2= ∑ i = 2 m K − i r 1 − i \sum_{i=2}^{m}K_{-i}r^{1-i} ∑i=2mK−ir1−i= R 1 − K − 1 R_{1}-K_{-1} R1−K−1= 0. K − 2 ⋯ K − m 0.K_{-2}\cdots{K_{-m}} 0.K−2⋯K−m
-
K − 2 K_{-2} K−2= [ R 2 / r − 1 ] [R_{2}/r^{-1}] [R2/r−1]= [ R 2 r ] [R_{2}r] [R2r]= [ ∑ i = 2 m K − i r 2 − i ] [\sum_{i=2}^{m}K_{-i}r^{2-i}] [∑i=2mK−ir2−i]= [ K 2 + ∑ i = 3 m K − i r 2 − i ] [K_{2}+\sum_{i=3}^{m}K_{-i}r^{2-i}] [K2+∑i=3mK−ir2−i],取出整数部分 K − 2 K_{-2} K−2,
- 剩余部分 R 3 R_{3} R3= ∑ i = 3 m K − i r 2 − i \sum_{i=3}^{m}K_{-i}r^{2-i} ∑i=3mK−ir2−i= R 2 r − K − 2 R_{2}r-K_{-2} R2r−K−2= 0. K − 3 ⋯ K − m 0.K_{-3}\cdots{K_{-m}} 0.K−3⋯K−m
-
…
-
K − i K_{-i} K−i= [ R i r ] [R_{i}r] [Rir],可以发现 R i = 0. K − i K − ( i + 1 ) ⋯ K − m R_{i}=0.K_{-i}K_{-(i+1)}\cdots{K_{-m}} Ri=0.K−iK−(i+1)⋯K−m,并且 r R i = K − i . K − ( i + 1 ) ⋯ K − m rR_{i}=K_{-i}.K_{-(i+1)}\cdots{K_{-m}} rRi=K−i.K−(i+1)⋯K−m
- R i + 1 R_{i+1} Ri+1= R i r − K − i R_{i}r-K_{-i} Rir−K−i= 0. K − ( i + 1 ) ⋯ K − m 0.K_{-(i+1)}\cdots{K_{-m}} 0.K−(i+1)⋯K−m
-
…
-
K − ( m − 1 ) K_{-(m-1)} K−(m−1)= [ R m − 1 r ] [R_{m-1}r] [Rm−1r], R m R_{m} Rm= R m − 1 r − K − ( m − 1 ) R_{m-1}r-K_{-(m-1)} Rm−1r−K−(m−1)= 0. K − m 0.K_{-m} 0.K−m
-
K − m K_{-m} K−m= [ R m r ] [R_{m}r] [Rmr], R m + 1 R_{m+1} Rm+1= R m r − K − m R_{m}r-K_{-m} Rmr−K−m= 0.0 0.0 0.0=0
-
如果 K − m K_{-m} K−m是最后一位( m m m是有限大的时候),根据上述分析, R m + 1 = 0 R_{m+1}=0 Rm+1=0
-
R a R_{a} Ra和 R b R_{b} Rb, ( a ≠ b , a , b ∈ { 1 , 2 , ⋯ , m } ) (a\neq{b},a,b\in\set{1,2,\cdots,{m}}) (a=b,a,b∈{1,2,⋯,m})之间没有必然的大小关系,我们也不关心谁大谁小
-
-
除了上述方法,还可以通过取模的方式来求小数数码
- R 1 r j R_{1}r^{j} R1rj= ∑ i = 1 m K − i r j − i \sum\limits_{i=1}^{m}K_{-i}r^{j-i} i=1∑mK−irj−i= ∑ i = 1 j K − i r j − i \sum\limits_{i=1}^{j}K_{-i}r^{j-i} i=1∑jK−irj−i+ ∑ i = j + 1 m K − i r j − i \sum\limits_{i=j+1}^{m}K_{-i}r^{j-i} i=j+1∑mK−irj−i= K − 1 r j − 1 + K − 2 r j − 2 + ⋯ + K − j + R j + 1 K_{-1}r^{j-1}+K_{-2}r^{j-2}+\cdots+{K_{-j}}+R_{j+1} K−1rj−1+K−2rj−2+⋯+K−j+Rj+1; ( R j = 0. K − j ⋯ K − m ) (R_{j}=0.K_{-j}\cdots{K_{-m}}) (Rj=0.K−j⋯K−m)
- 则 K − j = [ R 1 r j ] % r K_{-j}=[R_{1}r^{j}]\%{r} K−j=[R1rj]%r;并且当 j = m j=m j=m时, R m + 1 = R 1 r m − [ R 1 r m ] = 0 R_{m+1}=R_{1}r^{m}-[R_{1}r^{m}]=0 Rm+1=R1rm−[R1rm]=0;
-
第一种方法偏向递推,第二种方法偏向通项
在程序设计中,判断终止的条件都是小数部分是否为0,因此需要知道计算小数部分的方法:给定一个数 f f f,它的整数部分表示为 [ f ] [f] [f],小数部分为 f − [ f ] f-[f] f−[f],判断小数部分是否为零相当于判断这个差值是否为0
m m m不一定是一个有限的数
- 例如十进制数转为二进制数不一定是能够有一个有限位数的二进制数表达无损表达出来,在转换结束之前, m m m的取值是难以确定的,甚至是无穷大的(如果被转换的十进制数本身就是无穷小数,那么转换为二进制也一定是无穷的)
减权定位法👺
-
这是一类便于人类手算的快速方法,依赖于人们对于进制数的了解
-
以十进制转二进制为例,需要事先知道一些常用的2的幂的十进制取值,方便配合本方法操作
-
当十进制数较大时,采用减权定位法可减少重复除法(或乘法)的次数。
-
例 将十进制数 5148 转换成二进制数,可按下列步骤进行。
十进制数 位权 5148 − 4096 2 12 1052 − 1024 2 10 28 − 16 2 4 12 − 8 2 3 4 − 4 2 2 0 \begin{array}{r|l} \text{十进制数} & \text{位权} \\ \hline 5148 & \\ -4096 & 2^{12} \\ \hline 1052 & \\ -1024 & 2^{10} \\ \hline 28 &\\ -16 & 2^4 \\ \hline 12 & \\ -8 & 2^3 \\ \hline 4 & \\ -4 & 2^2 \\ \hline 0 & \end{array} 十进制数5148−40961052−102428−1612−84−40位权212210242322
-
2 12 , 2 11 , 2 10 , 2 9 , 2 8 , 2 7 , 2 6 , 2 5 , 2 4 , 2 3 , 2 2 , 2 1 , 2 0 2^{12}, 2^{11}, 2^{10}, 2^9, 2^8, 2^7, 2^6, 2^5, 2^4, 2^3, 2^2, 2^1, 2^0 212,211,210,29,28,27,26,25,24,23,22,21,20
-
2 12 2^{12} 212 2 11 2^{11} 211 2 10 2^{10} 210 2 9 2^9 29 2 8 2^8 28 2 7 2^7 27 2 6 2^6 26 2 5 2^5 25 2 4 2^4 24 2 3 2^{3} 23 2 2 2^2 22 2 1 2^1 21 2 0 2^0 20 1 0 1 0 0 0 0 0 1 1 1 0 0
即 ( 5148 ) 10 = ( 1010000011100 ) 2 (5148)_{10} = (1010000011100)_{2} (5148)10=(1010000011100)2。
-
利用这个方法的时候,需要知道5148以内的 2 k 2^{k} 2k幂的取值,那么做这个转换就比较快,
首先不超过 5148 5148 5148且最接近的2的幂是 2 12 = 4096 2^{12}=4096 212=4096只要从 5148 5148 5148 中减去所含的最大 2 2 2 的方幂 4096 4096 4096,根据 2 12 = 4096 2^{12}=4096 212=4096,确定该权值对应的二进制数的位置(即数位)
然后再从减得的 1052 1052 1052 中减去所含的最大 2 2 2 的方幂 1024 1024 1024,又得该权值对应的数位,这样依次继续,直到差为 0 0 0。最后在有权值的对应数位上添 1 1 1,无权值的对应数位上添 0 0 0,便得转换结果。
再举个简单的例子:1025转换为2进制: 1025 − 2 10 = 1025 − 1024 = 1 1025-2^{10}=1025-1024=1 1025−210=1025−1024=1, 1 − 2 0 = 1 − 1 = 0 1-2^{0}=1-1=0 1−20=1−1=0,所以 102 5 10 = 10000000001 1025_{10}=10000000001 102510=10000000001,这比起朴素方法要快得多
2^{10} | 2^9 | 2^8 | 2^7 | 2^6 | 2^5 | 2^4 | 2^{3} | 2^2 | 2^1 | 2^0 |
---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
C/C++编程语言中的实现说明
- C/C++中取模运算要求两个操作数都是整数,而不能作用于浮点数
- 如果 m m m不是一个有穷的数,那么可以设定精度,比如计算出10位后退出循环
示例
将十进制的0.1转换为二进制形式
- 根据上述讨论的方法,我们从高位小数往低位小数求
- K − 1 = [ 0.1 × 2 ] = [ 0.2 ] = 0 K_{-1}=[0.1\times2]=[0.2]=0 K−1=[0.1×2]=[0.2]=0
- K − 2 = [ 0.2 × 2 ] = [ 0.4 ] = 0 K_{-2}=[0.2\times{2}]=[0.4]=0 K−2=[0.2×2]=[0.4]=0
- K − 3 = [ 0.4 × 2 ] = [ 0.8 ] = 0 K_{-3}=[0.4\times{2}]=[0.8]=0 K−3=[0.4×2]=[0.8]=0
- K − 4 = [ 0.8 × 2 ] = [ 1.6 ] = 1 K_{-4}=[0.8\times{2}]=[1.6]=1 K−4=[0.8×2]=[1.6]=1
- K − 5 = [ 0.6 × 2 ] = [ 1.2 ] = 1 K_{-5}=[0.6\times{2}]=[1.2]=1 K−5=[0.6×2]=[1.2]=1
- K − 6 = [ 0.2 × 2 ] = [ 0.4 ] = 0 K_{-6}=[0.2\times{2}]=[0.4]=0 K−6=[0.2×2]=[0.4]=0
- 可以发现第 2 , 6 2,6 2,6两行是算式是一样的,可以断定,循环节为第 2 ∼ 5 2\sim{5} 2∼5行对应的共4个数码,循环节为 0011 0011 0011
- 从而
0.
1
10
0.1_{10}
0.110=
0.0
(
0011
)
(
0011
)
(
0011
)
.
.
.
2
0.0 (0011)(0011)(0011)..._{2}
0.0(0011)(0011)(0011)...2=
0.0001100110011..
.
2
0.0 001100110011..._{2}
0.0001100110011...2
- 可以手算验证,看看是否随着位数的增加结果雨来月接近0.1
- 或者用计算机计算器验证,比如使用qalculate
- 并且可以断定,有限位的二进制数无法准确表达 0.1 0.1 0.1,会损失一定精度,在计算机二进制中,保存0,1这种数存在一个精度问题
- 并且,经过上述讨论,可以知道0.2,0.4,0.8,1.2,1.6,都无法被有限的二进制数精确表达
- 类似的,可以验证0.3,0.6,0.7,0.9也不能被二进制数精确表达
- 而0.5可以,因为 0.5 × 2 0.5\times{2} 0.5×2= 1 1 1,小数部分为0,直接断定 0. 5 10 0.5_{10} 0.510= 0. 1 2 0.1_{2} 0.12,能够精确表达
十进制小数中可以被位数有限的二进制形式精确表达的条件
- 不妨设满足该添加的数为 x x x,所有这样的数构成的集合为 S S S
- 事实上,我们可以反过来探索能够被二进制数精确表达的十进制数,对于一个可以被有限位二进制小数精确表达的数,不妨设其为 0. K − 1 K − 2 ⋯ K − m 0.K_{-1}K_{-2}\cdots{K_{-m}} 0.K−1K−2⋯K−m,那么其对应的十进制数为 ∑ i = 1 m K − i 2 − i \sum_{i=1}^{m}K_{-i}2^{-i} ∑i=1mK−i2−i, K i ∈ { 0 , 1 } , m ∈ { 0 , 1 , 2 , ⋯ } K_{i}\in\set{0,1},m\in\set{0,1,2,\cdots} Ki∈{0,1},m∈{0,1,2,⋯}
- 那么 x ∈ { y ∣ y = ∑ i = 1 m K − i 2 − i , K i ∈ { 0 , 1 } , m ∈ { 0 , 1 , 2 , ⋯ } } x\in\set{y|y=\sum_{i=1}^{m}K_{-i}2^{-i},K_{i}\in\set{0,1},m\in\set{0,1,2,\cdots}} x∈{y∣y=∑i=1mK−i2−i,Ki∈{0,1},m∈{0,1,2,⋯}}
- 更一般的,可以推广到
r
1
r_1
r1进制的小数能够别
r
2
r_2
r2进制所精确表示的条件
- x ∈ { y ∣ y = ∑ i = 1 m K − i r 2 − i , K i ∈ { 0 , 1 , ⋯ , r 2 − 1 } , m ∈ { 0 , 1 , 2 , ⋯ } } x\in\set{y|y=\sum_{i=1}^{m}K_{-i}r_{2}^{-i},K_{i}\in\set{0,1,\cdots,r_{2}-1},m\in\set{0,1,2,\cdots}} x∈{y∣y=∑i=1mK−ir2−i,Ki∈{0,1,⋯,r2−1},m∈{0,1,2,⋯}}
相关规律@带余除法的应用
- 用向下取整的性质来讨论相关问题
-
由 K i K_i Ki的取值范围(最大为 r − 1 r-1 r−1)可知 K i / r K_i/r Ki/r的向下取整结果为0: [ K i / r ] = 0 [K_i/r]=0 [Ki/r]=0
-
K i r i ⩽ ( r − 1 ) r i < r i + 1 K_{i}r^{i}\leqslant{(r-1)r^{i}}<r^{i+1} Kiri⩽(r−1)ri<ri+1
-
小数点移位
对于 S r S_{r} Sr= K n ⋯ K 0 . K − 1 K − 2 ⋯ K − m K_{n}\cdots{K_{0}}.K_{-1}K_{-2}\cdots{K_{-m}} Kn⋯K0.K−1K−2⋯K−m,
表达式 S r / r k S_{r}/r^{k} Sr/rk= K n ⋯ K k . K k − 1 ⋯ K 0 K − 1 K − 2 ⋯ K − m K_{n}\cdots K_{k}.K_{k-1}\cdots {K_{0}}K_{-1}K_{-2}\cdots{K_{-m}} Kn⋯Kk.Kk−1⋯K0K−1K−2⋯K−m,其中
- K n ⋯ K k K_{n}\cdots K_{k} Kn⋯Kk是 S r / r k S_{r}/r^{k} Sr/rk的整数部分,即 S r / r k S_{r}/r^{k} Sr/rk= [ K n ⋯ K k ] [K_{n}\cdots K_{k}] [Kn⋯Kk];
- K k − 1 ⋯ K − m K_{k-1}\cdots{K_{-m}} Kk−1⋯K−m是 S r / r k S_{r}/r^{k} Sr/rk的小数部分,显然 0. K k − 1 ⋯ K − m < 1 0.K_{k-1}\cdots{K_{-m}}<1 0.Kk−1⋯K−m<1
反之,如果 S r × r k S_{r}\times{r^{k}} Sr×rk,则表示 S r S_{r} Sr的小数点向右移动 k k k位
上述结论基于进位计数法的定义可以验证
例如,我在十进制数 1234.567 1234.567 1234.567,对其除以权的3次方,即 1 0 3 10^{3} 103,结果为 1.234567 1.234567 1.234567,小数点挪动了3位;
利用该结论,我们可以取 S r S_{r} Sr的最高位(设最高位为 K n K_{n} Kn),则 K n K_{n} Kn= [ S r / r n ] [S_{r}/r^{n}] [Sr/rn];
注意,整数部分的最高位 K n K_{n} Kn从右 ( K 0 ) (K_{0}) (K0)往左数是第 n + 1 n+1 n+1位( n ⩾ 0 n\geqslant{0} n⩾0)
例如S=43210的最高位可以通过 [ S / 1 0 4 ] = 4 [S/10^{4}]=4 [S/104]=4求得
-
[ ∑ i = 0 n K i r i r n ] = K n ⋅ 1 + [ ∑ i = 0 n − 1 K i r i r n ] = K n + 0 = K n \left[ {\frac{\sum\limits_{i=0}^{n}K_{i}r^{i}}{r^n}} \right] =K_n\cdot{1}+ \left[ {\frac{\sum\limits_{i=0}^{n-1}K_{i}r^{i}}{r^n}} \right] =K_n+0=K_n rni=0∑nKiri =Kn⋅1+ rni=0∑n−1Kiri =Kn+0=Kn
因此理论上我们也可以从最高位 开始算,但是需要知道最终结果有几位(也就是要提前知道 n n n),否则只能从低位开始算
下面从另一个角度说明, S r / r k S_{r}/r^{k} Sr/rk的余数问题,这部分和数论中的带余除法相关
令 S r S_{r} Sr的整数部分为 Z = K n ⋯ K k ⋯ K 1 K 0 Z=K_{n}\cdots K_{k}\cdots K_{1}K_{0} Z=Kn⋯Kk⋯K1K0
-
Z = ∑ i = 0 n K i r i Z=\sum_{i=0}^{n}K_{i}r^{i} Z=∑i=0nKiri; R = Z r k = ∑ i = 0 n K i r i − k R=\frac{Z}{r^k}=\sum_{i=0}^{n}K_{i}r^{i-k} R=rkZ=∑i=0nKiri−k
-
现在我们从计算的角度判断 R < 1 R<1 R<1或对于 R 0 = R r k R_{0}=Rr^{k} R0=Rrk= ∑ i = 0 k − 1 K i r i \sum_{i=0}^{k-1}K_{i}r^{i} ∑i=0k−1Kiri , R 0 < r k R_{0} < r^{k} R0<rk是否正确(连个命题等价)
- 对 R 0 R_{0} R0利用 K i ⩽ r − 1 K_{i}\leqslant{r-1} Ki⩽r−1来放大,得到 T = ∑ i = 0 k − 1 ( r − 1 ) r i T={\sum_{i=0}^{k-1}(r-1)r^{i}} T=∑i=0k−1(r−1)ri= ( r − 1 ) ∑ i = 0 k − 1 r i (r-1)\sum_{i=0}^{k-1}r^{i} (r−1)∑i=0k−1ri,由等比数列求和公式可得
- T = ( r − 1 ) r k − 1 r − r 0 r − 1 T=(r-1)\frac{r^{k-1}r-r^{0}}{r-1} T=(r−1)r−1rk−1r−r0= r k − 1 r^{k}-1 rk−1
- 由此可见 R 0 ⩽ T < r k R_{0}\leqslant{T}<r^{k} R0⩽T<rk
-
令 Q = K n K n − 1 ⋯ K k Q=K_{n}K_{n-1}\cdots{K_{k}} Q=KnKn−1⋯Kk= ∑ i = k n K i r i − k \sum_{i=k}^{n}K_{i}r^{i-k} ∑i=knKiri−k, R 0 = ∑ i = 0 k − 1 K i r i R_{0}=\sum_{i=0}^{k-1}K_{i}r^{i} R0=∑i=0k−1Kiri; q = r k q=r^{k} q=rk
-
从带余除法的角度有 S r = Q q + R 0 S_{r}=Qq+R_{0} Sr=Qq+R0,其中 R 0 ∈ [ 0 , q ) R_{0}\in[0,q) R0∈[0,q)
-
[ Z r k ] [\frac{Z}{r^k}] [rkZ]= Q Q Q= K n ⋯ K k K_{n}\cdots K_{k} Kn⋯Kk,但是此时的权分别为 r n − k , r n − k − 1 ⋯ , 1 r^{n-k},r^{n-k-1}\cdots,1 rn−k,rn−k−1⋯,1
-
K i = [ Z r i ] % r K_i=[\frac{Z}{r^i}]\%r Ki=[riZ]%r
-
例如, S = 32123 S=32123 S=32123, S S S= 321 × 1 0 2 + 23 321\times{10^{2}}+23 321×102+23
小结
-
整数部分:
-
通项公式:
-
K i = [ Z r i ] % r , ( i = 0 , 1 , 2 , ⋯ , n ) K_i=[\frac{Z}{r^i}]\%r,(i=0,1,2,\cdots,n) Ki=[riZ]%r,(i=0,1,2,⋯,n)
- 当 [ Z r k ] = 0 [\frac{Z}{r^k}]=0 [rkZ]=0时,结束整数部分转换
-
-
-
小数部分
-
通项公式
-
类似的分析,可以得到小数部分的通项公式
-
K s = [ D r − s ] % r = [ r s D ] % r K_s=[\frac{D}{r^{-s}}]\%r=[r^sD]\%r Ks=[r−sD]%r=[rsD]%r
- 当 r s D − [ r s D ] = 0 r^sD-[r^sD]=0 rsD−[rsD]=0(或 r s D = [ r s D ] r^{s}D=[r^{s}D] rsD=[rsD])时结束小数部分的转换
-
-
-
事实上,整数部分和小数部分的公式是一致的(小数部分虽然变成乘法,但是实际上是由 D / r − s D/r^{-s} D/r−s变形而来的)
注意
-
不是所有十进制数都可以用有限位二进制准确表示出来,例如0.3,2.88
-
r 1 < r 2 r_1<r_2 r1<r2
- r 1 − k > r 2 − k r_1^{-k}>r_2^{-k} r1−k>r2−k
- 可以直观感受到基数小的位权在小数部分比基数大的反而要粗糙
- 例如二进制一位小数只能表示
0.0
或0.1
两个值,而十进制一位小数可以表示10个值,可以看出基数小的数想要表示和基数大的数相同(或近似)的数往往需要更多的位
判断一个十进制小数能否被表示为有限位r进制
讨论这个问题,下面用到了数论中的算数基本定理
我们以十进制数0.3为例进行讨论
判断十进制小数
x
10
=
0.3
x_{10} = 0.3
x10=0.3能否被
r
r
r进制精确表示(使用有限位(m位)表示)
那么可以设:
0.3
=
∑
i
=
1
m
K
−
i
r
−
i
0.3=\sum_{i=1}^mK_{-i}r^{-i}
0.3=∑i=1mK−ir−i
那么对上式两边同时乘以
r
m
r^m
rm,得到
0.3 r m = ∑ i = 1 m K − i r m − i ∈ Z 0.3r^m=\sum_{i=1}^mK_{-i}r^{m-i}\in\mathbb{Z} 0.3rm=∑i=1mK−irm−i∈Z
可以确保等式右侧为整数 ,不妨记为
S
S
S
相应的左侧应该也是整数,否则假设不成立
S
=
0.3
⋅
r
m
∈
Z
S=0.3\cdot{r}^m\in\mathbb{Z}
S=0.3⋅rm∈Z
例如
考虑 0.3 0.3 0.3能否被表示为位数有限的 r = 2 r=2 r=2进制形式
S S S= 0.3 ⋅ 2 m = 3 10 2 m = 3 5 2 m − 1 0.3\cdot{2^{m}}=\frac{3}{10}2^m=\frac{3}{5}2^{m-1} 0.3⋅2m=1032m=532m−1 ∈ Z \in{\mathbb{Z}} ∈Z
问题在于 S S S= 3 ⋅ 2 m − 1 5 \frac{3\cdot{2^{m-1}}}{5} 53⋅2m−1是否有整数解,等式变形为 T = 5 S = 3 ⋅ 2 m − 1 T=5S=3\cdot{2^{m-1}} T=5S=3⋅2m−1;由于 S S S是整数,显然T是整数,并且 5 , 3 , 2 5,3,2 5,3,2都是 T T T的质数约数
将这个连等式分开表示
T
=
5
S
T=5S
T=5S;(1)
T
=
3
⋅
2
m
−
1
T=3\cdot{2^{m-1}}
T=3⋅2m−1(2)
式(1)表明 5 5 5是 T T T的一个素数约数,对于式(2)根据算数基本定理, T T T的素数约数只有 3 , 2 3,2 3,2,这是矛盾的,所以 m m m不是一个整数,从而十进制 0.3 0.3 0.3无法被精确得表示为二进制形式
十进制转任意进制的方法总结👺
- 根据上面的讨论(十进制转任意进制)
- 整数部分的转换方法称为:除基取余法
- 小数部分的转换方法称为:乘基取整法
- 两个方法从形式和操作上看,恰好是反过来的