代码改变世界

整数的展开

2011-03-14 00:33 by Anders Cui, ... 阅读, ... 评论, 收藏, 编辑

十进制计数

日常生活中整数最常见的表示形式为十进制。如965,它的值是9*10^2+6*10+5。从最开始接触数字,我们就在用十进制计数,可以确信对于任何一个非负整数n,都可以唯一地表示为如下的形式:

数的展开_html_m945cbdf(公式1)

其中,k是非负整数,数的展开_html_m82111c2是小于10的非负整数(也即0到9)。可以将这个数字的表示简化为数的展开_html_m405528d,这也正是我们所习惯的形式,一般把n称为(k+1)位数,如965是一个3位数。虽然根据经验可以得出,任何一个正整数n,都可以唯一地表示为上面的十进制形式,这里还是简单地证明一下(对下面的另外一种展开会有帮助)。

这里的证明需要分为两部分,一是存在性,二是唯一性。

存在性:对于数的展开_html_m7f04a07d来说,它所能表示的最大数为数的展开_html_6304d6b,如果可以证明它可以表示所有0到数的展开_html_4d8d9eff范围内的整数,就可以证明存在性了。这里采用归纳法:

基础步骤:k=0时,数的展开_html_54d8fb0d可以表示0-9(即0到数的展开_html_m160f3b8)范围内的所有整数;

归纳步骤:假设对于整数m来说,命题成立,这样数的展开_html_12c49e5d可以表示0到数的展开_html_35e153a范围内的所有整数。考虑整数n,它满足数的展开_html_m70595db4,注意到数的展开_html_6f606342,所以存在整数数的展开_html_m352cd680数的展开_html_22c1566),使得数的展开_html_18caf09f,也就是说数的展开_html_m316fbae可以表示所有0到数的展开_html_m3e2eb306范围内的整数。

这样,对于任意正整数n,总可以找到一个十进制数数的展开_html_m405528d来表示,其中k=数的展开_html_m47dbf7a3([]为下取整函数)。

唯一性:可以用反证法证明,这里从略。

nb进制展开

在计算机系统当中,使用更多的还是二进制、八进制和十六进制。上面十进制表示的结论也可以推广到任意的正整数b(b>1),也就是说,对于任意一个非负整数n,都可以唯一地表示为如下的形式:

数的展开_html_m146f58ff(公式2)

这个形式可以称为n以b为基数(base)的展开,或者n的b进制展开,记为数的展开_html_m828b487。当b=2时,也就是我们非常熟悉的二进制展开了,很多时候会遇到这方面的面试题:如何表示一个整数,二进制展开中有多少个1等等。那现在来考虑给定一个正整数n和基数b(b>1),如何求得n的b进制展开呢?通过公式2可以看到,迭代地使用带余除法,直到商为0即可。

private static readonly string digitTable = "0123456789abcdef";
private static readonly int maxBase = digitTable.Length;

/// <summary>
/// Base b expansion.
/// </summary>
/// <param name="n">n >= 0</param>
/// <param name="b">b in [2, 16]</param>
/// <returns></returns>
public static string Expansion(int n, int b)
{
Stack
<string> remainders = new Stack<string>();
do
{
remainders.Push((n
% b).ToString());
n
/= b;
}
while (n > 0);

return string.Join(string.Empty, remainders.ToArray());
}

如果n=165,b=8,则结果为245。

其它的展开形式

有趣的是,在对一个整数进行展开时,除了上面提到的b进制展开,还有其它形式的展开。比如康托尔(Cantor)展开,它是说对于任意一个非负整数n可以唯一地表示为如下的形式:

数的展开_html_mb061b83,其中数的展开_html_4a726c85为整数,且数的展开_html_m44d5da31,i=1,2,...,n。

这个看起来有点儿不可思议。对于十进制展开来说,我们可以相信它可以连续地表示所有非负整数,而康托尔展开就没那么明显了。现在再次观察十进制展开数的展开_html_m7ed99a95,它为何能够连续地表示整数呢?一个k位数能够表示0到数的展开_html_6304d6b范围内的整数,而数的展开_html_6304d6b的下一个整数整数数的展开_html_m167c4539正好是一个(k+1)位数的最小值,这是关键之处。而它能够唯一地表示整数,在于如果i与j不相等,那么一个i位数和一个j位数就不可能相等,这样可以将所有整数按段来分隔了。

下面来考虑康托尔展开是否具有上段提到的两个性质。对于数的展开_html_76bf8322,可以记为数的展开_html_m476637db,这样仍然可以用一位数、两位数来称呼它们。对于一位数,即k=1时,康托尔展开可以表示的数是0、1;对于两位数,即k=2时,康托尔展开可以表示的数是2、3、4、5;而三位数则可以表示6、7、...、23。看来至少在k不大于3时是可以连续、唯一地表示整数的。一般地,等式成立(可以用数学归纳法证明),而这一等式使得康托尔展开就跟上段提到的十进制展开的两个性质非常类似,这样就可以初步确定康托尔展开可以唯一地表示任意的非负整数了,详细的证明过程与十进制展开的证明类似,不再赘述。

参考:
离散数学及其应用
数据结构与问题求解