1.进位制数
日常生活中人们都采用十进制数,十进制数用0、1、2、3、4、5、6、7、8、9十个数码表示数值;其基数为10,规则逢十进一,借一当十。
计算机中采用二进制数,二进制数只用两个数码0和1来表示数值;其基数为2,规则逢二进一,借一当二。
由于二进制数书写比较麻烦,因此,计算机中通常又用八进制数或十六进制数来书写和表示信息。
八进制数用0、1、2、3、4、5、6、7八个数码表示数值;其基数为8,规则逢八进一,借一当八。
十六进制数用0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F十六个数码表示数值(在这十六个数码中的A、B、C、D、E、F六个数码,分别代表十进制数中的10、11、12、13、14、15,这是国际上通用的表示法);其基数为16,规则逢十六进一,借一当十六。
一般来说,若把它们统称为 R进制,则R进位制具有下列特点:
(1)在R进制中,具有R个数字符号,它们是0,l,…,(R- 1)。
(2)在R进制中,由低位向高位是按“逢R进一”的规则进行计数。
(3)R进制的基数是“R”,R进制数的第 i位的权为“Ri”,约定整数最低位的位序号i为0(i=n,…2,l,0,-l,-2…)。
基数和位权是进位制数的两个要素。所谓某进位制的基数是指该进位制中允许选用的基本数码的个数。不同进位制具有不同的基数,基数表明了某一进位制的基本特征,例如对于二进制,有两个数码(0,1),且由低位向高位是“逢二进一”,故其基数为2。对于某一进位制数,一个数码处在数的不同位置时,它所代表的数值是不同的。例如在十进制数333中,数字3在个位数位置上时表示3,即3×100;数字3在十位数位置上时表示30,即3×101;数字3在百位数位置上时表示300,即3×102。可见每个数码所表示的数值等于该数码乘以一个与数码所在位置有关的常数,这个常数叫位权。位权的大小是以基数为底、数码所在位置的序号为指数的整数次幂。位权表明了同一数字符号处于不同数位时所代表的值不同。
一般而言,对于任意的R进制数
An-1An-2…A1A0 . A-1A-2…A-m (其中n为整数位数,m为小数位数)
可以表示为以下和式:
An-1×Rn-1 +…+A1×R1+A0×R0+A-1×R-1+…A-m×R-m (其中R为基数)
上式称为“按权展开式”。
我们可以用圆括号外的下标值(如:10、2、8、16)表示该括号内的数是哪一个进位制中的数,或在数的最后加上字母D(十进制、D可省略)、B(二进制)、Q(八进制)、H(十六进制)来区分其前面的数是属于哪个进位制。例如,十进制数25可以表示为(25)10或25D或25;二进制数101可以表示为101B或(101)2 。
2.进位制数的相互转换
同一个数值可以用不同的进位制数表示,例如对于十进制数12,可以表示为二进制数1100,可以表示为八进制数14,也可以表示为十六进制数0C。这表明不同进位制只是表示数的不同手段,它们之间必定可以相互转换。下面具体介绍计算机中常用的几种进位制数之间的转换,即十进制与二进制数之间的转换,十进制与八进制或十六进制数之间的转换。
(1)十进制数转换为二进制数
十进制数转换为二进制数的基本方法是:对于整数采用“除2取余”,对于小数采用“乘2取整”。具体做法为:对于十进制数整数,用2连续除要转换的十进制整数及各次所得之商,直除到商等于0时为止,则各次所得之余数即为所求二进制整数由低位到高位的值;对于十进制小数,用2连续乘要转换的十进制小数及各次所得之积的小数部分,直乘到积的小数部分为0(或满足所要求的精度)时为止,则各次所得之积的整数部分即为所求二进制小数由高位到低位的值。当十进制数包含有整数和小数两部分时,可分别将整数和小数转换,然后相加。
例1 将十进制数53.375转换成二进制数。
于是, 53.375 = 110101.011B 。
(2)二进制数转换为十进制数
二进制数转换为十进制数的基本方法是将二进制数的各位按权展开相加。
例2 将二进制数11011.101转换成十进制数
11011.101B =1×24+1×23+0×22+1×21+1×20+1×2-1+0×2-2+1×2-3
=16+8+0+2+1+0.5+0+0.125 =27.625
于是, 11011.101B =27.625 。
【例1】逆序的二进制数
问题描述
把一个十进制整数转换成二进制,然后将其二进制倒过来得到的新的数的十进制是多少?
例如,十进制整数6的二进制数为110,逆序后为011,去掉前导0,得到的新数为11,对应的十进制数为3。
输入
输入第1行为一个整数T(1≤T≤100),表示测试用例的组数。
之后T行,每行为1个十进制整数X(0≤X≤231−1)。
输出
二进制数逆序后得到的新的十进制数。
输入样例
3
6
8
1
输出样例
3
1
1
(1)编程思路。
直接采用“除2取余”的方法将输入的十进制整数转换为二进制数保存到a数组中,a[0]保存二进制数的最低位。之后将数组a中保存的二进制数码按权值展开即得到逆序后的十进制数。
(2)源程序。
#include <stdio.h> int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); int a[32]; int len=0; // 保存n对应的二进制的位数 while(n) // 将n转换为二进制数并保存到数组a中 { a[len++] = n%2; n/=2; } int k; for (k=0;k<len && a[k]==0; k++) ; // 去掉前导0 int i,ans = 0; for (i=k;i<len;i++) // 去掉前导0后,a[k]~a[len-1]正好是逆序后的二进制数 { ans=ans*2+a[i]; } printf("%dn",ans); } return 0; }
将上面的源程序提交给“http://acm.hdu.edu.cn/showproblem.php?pid=5142 NPY and FFT”,可以Accepted。
(3)十进制数转换为R进制数
类似于十进制数转换为二进制数的方法,十进制数转换为R进制数的基本方法是:对于整数采用“除R取余”,对于小数采用“乘R取整”。具体做法为:对于十进制数整数,用R连续除要转换的十进制整数及各次所得之商,直除到商等于0时为止,则各次所得之余数即为所求R进制整数由低位到高位的值;对于十进制小数,用R连续乘要转换的十进制小数及各次所得之积的小数部分,直乘到积的小数部分为0(或满足所要求的精度)时为止,则各次所得之积的整数部分即为所求R进制小数由高位到低位的值。当十进制数包含有整数和小数两部分时,可分别将整数和小数转换,然后相加。
(4)R进制数转换为十进制数
R进制数转换为十进制数的基本方法是将R进制数的各位按权展开,然后进行十进制数相加即可。
【例2】十进制数转换为M进制数
问题描述
将一个十进制数X(1<=X<=10^9)转换成任意进制数M(2<=M<=16)。
输入
一行两个正整数X和M。
输出
输出X的M进制的表示。
输入样例
31 16
输出样例
1F
(1)编程思路1。
直接采用“除M取余”的方法将十进制整数X转换为M进制数。
(2)源程序1。
#include <stdio.h> #include <string.h> char table[16]="0123456789ABCDEF"; int main() { int x,m; scanf("%d%d",&x,&m); char num[33]; int i,j,k=0; do { num[k++]=table[x%m]; x/=m; } while (x!=0); num[k]='