道生一(二)

        人类普遍使用十进制,只不过是绝大多数人生来就有十个手指这样一个解剖学事实的结果。

--亚里士多德

        道生一,一生二,二生三,三生万物。

--老子


        上一篇文章里面我们讨论了“数”和“数的表示”之间的区别“。”数“是用来描述物质的物理属性的量度的一个抽象概念,一个数可以有多种不同的表示方法,在不同的语境中,你可以选择不同的方式来表示一个数值。我们把用来表示数值的机制称为“计数系统”。

计数系统


        想象一下我们投票的时候使用的计票方式:

                

         上面的记法表示十进制的数值23。再来看看使用一种叫做tally-slash的计数系统怎么表示数值23:

                

         上面是两种典型的非位值计数系统。非位值计数系统使用n个符号来表示正整数n(如上面用23条笔画或者23根线段来表示数值23)。这种计数系统最大的优点就是直观,对实物进行计数时比较方便,但缺点是体积庞大,无法表示大数,并且尤其难以进行数学运算,想想上一篇文章开头的那个关于“万”字的笑话。

        位值计数系统使用符号出现的位置来表示额外的信息,也就是说一个符号所代表的数值由符号本身和符号出现的位值共同决定。应用最广泛的位值计数系统当然是十进制计数系统了,十进制计数系统使用0-9十个阿拉伯数字作为计数符号。例如,十进制整数314所表示的数值实际上是:

            3 * 10^2 + 1 * 10^1 + 4 * 10^0

        看到形如“314”这样的符号,我们不必经过上面的转换来的得到它所表示的真正的数值,因为我们早已对十进制的“符号-数值”关联烂熟于心。

        位值计数系统使用比非位值计数系统少得多的空间来表示数值,而且极其适合应用于数学运算中。

        在计算机系统中广泛使用的位值计数系统却是二进制。计算机的底层基础是开关电路,只能表示“开”和“关”(或者说“0”和“1”)两个状态,因此使用二进制十分方便。既然我们不能强制要求计算机像我们一样思考,那么我们只能学习“如何像计算机一样思考”。二进制计数系统使用0和1两个阿拉伯数字作为计数符号。对于一个二进制数1101,它所表示的数值实际上是:

            1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0
            或 8 + 4 + 0 + 1
            或 (13) 10  (下标10代表使用的计数系统是十进制)


基底


         十进制计数系统的基底是10,二进制计数系统的基底是2。类似的,我们可以构建m进制计数系统(m为正整数且m>=2),显而易见的,m进制计数系统需要使用m个符号来表示从0到m-1(包括0和m-1)之间的m个正整数。一个m进制正整数k可以表示为:

            (a n a n-1 a n-1 ...a 1 a 0 ) m     (a 属于集合 [0, m-1])

          它所表示的数值实际上是:

              k = a m^n + a n-1  m^(n-1) + ... + a * m^1 + a * m^0

        在计算机系统中,我们有时候还使用八进制或者十六进制计数系统。八进制计数系统使用0-7八个阿拉伯数字作为计数符号,十六进制计数系统使用0-9十个阿拉伯数字加上a-f(或者A-F)六个英文字母作为计数符号。

        使用二进制计数系统表示的数十分冗长,直接阅读二进制数并不是一件很愉快的事情。在这个时候,使用十六进制来代替二进制是很便利的。而且十六进制有一个很好的特点,那就是十六进制数的每一位数(不管其位值如何)总是对应着一个唯一的四位二进制数。这是因为二进制以2为基底,十六进制以16为基底,而16=2^4。这让我们可以在这两种计数系统之间便利地进行转换。它们的对应关系如下:

十六进制-二进制转换表
十六进制 二进制
 0 0000
 1 0001
 2 0010
 3 0011
 4 0100
 5 0101
 6 0110
 7 0111
 8 1000
 9 1001
 A 1010
 B 1011
 C 1100
 D 1101
 E 1110
 F 1111

         例如,十六进制F1可以通过查表很方便地转换为二进制11110001。

数制转换


         怎么把一个十进制数转换成任意进制数呢?我们重点讨论怎么把十进制数转换成二进制数,十进制向其他进制的转换与此类似。对于一个十进制数k,假设其二进制形式可以表示为:

             k =   (a n a n-1 a n-1 ...a 1 a 0 ) 2     (a属于集合[0, 1])
                =  a* 2^n + an-1 * 2^(n-1) + ... + a* 2^1 + a* 2^0

         我们的任务就是求得每一项的系数a,这可以通过多次求余和整除运算来完成。

                 a 0 = k % 2,          k 1 = k / 2
            a 1 = k 1 % 2,        k 2 = k 1 / 2
            ....
            a n-1 = k n-1 % 2,    k n = k n-1 / 2
             a n = k n % 2,         k n+1 = k n / 2 = 0    (终止)

算法描述:
STEP1: 取得k除以2的余数,插入到结果集
STEP2: 取得k整除2的商,把商赋给k
STEP3: 如果k等于0,则算法结束
STEP4: 否则,取得k除以2的,前置插入到结果集
STEP5: 转到STEP2


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值