任务描述
请编写一个Python程序,实现十进制整数到二进制整数的转换;
请编写一个Python程序,实现十进制小数到二进制小数的转换。请注意,length参数用于指定转换后二进制位数;
请编写一个Python程序,实现二进制整数分别到八进制和十六进制整数的转换。请注意,由参数oh来指定是转成八进制(’o’)还是十六进制(’h’)。
相关知识
一个数值能够用不同进制表示,这些表示之间存在转换关系。计算机使用二进制表示数值,而人类惯用十进制。当将数值输入到计算机中时,必须将十进制转换为二进制,而将计算机中的数值输出时,一般要将其转换为十进制,以便于人阅读和理解。对整数而言,虽然进制不同,但是一个数的不同进制表示在数值上是相等的,因此有:
(N)
10
=a
n
×2
n
+⋯+a
1
×2
1
+a
0
×2
0
(1)
上式等号左边下标10表示用十进制表示整数N。由上式可得,将二进制整数转换为十进制整数,可直接按照等号右边的式子,做十进制的乘法和加法就能完成。例如,二进制整数(10111)
2
可按照上式转换为十进制整数:
1×2
4
+0×2
3
+1×2
2
+1×2
1
+1×2
0
=(23)
10
而十进制整数到二进制整数的转换可采用“除2取余”法,其方法也可由上式推导出来。N代表给定的十进制整数,a
n
、…a
1
、a
0
分别代表需要求出的各位二进制数字。(1)式等号两边同时除以2,等式保持不变。从等式右边可看出,N除以2得到的余数是a
0
,得到的商为a
n
×2
n−1
+⋯+a
2
×2
1
+a
1
,对商再除以2,又得余数a
1
和商a
n
×2
n−2
+⋯+a
3
×2
1
+a
2
,等等,依此进行下去,直到商为0。这个过程中得到的所有余数或为0 或为1,将它们按照求得的顺序的反序拼接在一起,就得到所需要的二进制表示形式。
如下图1给出了将(37)
10
转换成二进制的过程,所得结果为:
(37)
10
=(100101)
2
。
二进制小数与十进制小数之间的转换方法也能通过公式推导出来。如下式所示,其中0.a-1a-2… a-m是二进制小数,下标m可能为无穷大,N是等价的十进制小数,下标m可能为无穷大,N是等价的十进制小数。
(N)
10
=a
−1
×2
−1
+a
−2
×2
−2
++⋯+a
−m
×2
−m
(2)
同样地,将二进制小数转换为十进制小数,可直接按照等号右边的式子,做十进制的除法和加法即可。例如,已知(0.1011)
2
,求其等价的十进制小数,转换过程为:
1×2
−1
+0×2
−2
+1×2
−3
+1×2
−4
=(0.6875)
10
十进制小数到二进制小数的转换可采用“乘2取整”法,将公式(2)两边同时乘以2,等式仍成立,此时,右边整数部分变成a
−1
,小数部分变为:
a
−2
×2
−1
+a
−3
×2
−2
+⋯+a
−m
×2
−m+1
再对结果的小数部分两边乘以2,右边整数部分变成a
−2
,小数部分为:
a
−3
×2
−1
+⋯+a
−m
×2
−m+2
依此进行下去,直到乘2的结果中小数部分为0,或者达到所需要的二进制位数。对于很多十进制小数,上述乘2的过程,达不到结果小数部分为0的情形。因此,十进制小数到二进制小数的转换是不精确的转换。下图2中给出了十进制小数到二进制小数转换的两个例子,左边是将十进制数0.625转换成二进制数,它是精确转换;右边是将十进制数0.34转换成二进制数,它是不精确转换。从图中可得:
从图2的例子还可知道,用二进制来表示十进制数时,有些数不能精确表示,只能在表示能力范围内给出近似表示。这与可用的二进制位数和十进制数自身相关:
可用的二进制位数是由计算机的能力决定的,对32位计算机,可以用来表示数的位数通常有8、16和32位,位数越多,能表示的数值越多,精度也越高;
对不能精确转化为二进制的十进制小数,即便能用的二进制位数很多,也无法精确地表示出来。例如,0.1这个十进制小数转换成二进制小数是一个无限循环小数,理论上就无法精确表示。
除了表示数值,还需表示数值的符号: 如“+”或“-”。通常用二进制表示的最高位来表示数值的符号位,0表示正数、1表示负数。因此,如果能用的二进制位为8位,那么,(23)
10
=(00010111)
2
。
而(−23)
10
=(10010111)
2
,这种表示方式称为原码表示。
计算机中通常用浮点数来表示实数,浮点数是指有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意的某个实数。浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。考察下面的Python语句:
>>>print(0.1)
0.1
>>>print("%.17lf" % 0.1)
0.10000000000000001
0.1这个十进制小数转换成二进制数时,是一个无限循环小数,在计算机中通常用浮点数表示,是一种近似的表示。而现代程序设计语言的输出带有一定的智能,在保证误差较小的前提下会自动舍入。所以第一个print语句打印0.1。但是,当用第2个print语句指定输出精度时,就能看到0.1在计算机中不是真正的0.1,而是有一定的误差的。同理,浮点数之间用>、<、==来比较大小是不可取的,需要看两个浮点数是否在合理的误差范围,如果误差合理,即认为相等;否则,两个在十进制中相等的数可能在计算机中是不相等的。
此外,浮点数的误差会在其计算过程中累积,考察下面的Python程序:
x = 0.0
for i in range(100):
x += 0.1
print("%.17lf" % x)
print(x)
运行该程序得到的输出如下所示:第1行是x的较为精确的表示,而第2行是print自动舍入,显示出来的看似正确的结果。
9.99999999999998046
10.0
八进制和十六进制是计算机领域使用的辅助计数法,用于计算机与人类的交互。八进制或十六进制与二进制之间的转换很直观和简单,在认知上接近二进制。这些原因促进人们引入八进制和十六进制。由于这两种进制是辅助计数方法,人们不关心对八进制数或十六进制数的运算,在此对八进制运算和十六进制的运算不进行讨论。
八进制的基本组成为:
基本数字符号有八个,分别是0、1、2、3、4、5、6、7;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢八进一”;
基本运算(不予讨论)。
2374、101、0.564、3.21和11.101等都是合法的八进制数表示,而9021、11.2.5和76+2等都不是合法的八进制数字串。注意八进制串(101)
8
代表的数值与二进制串(101)
2
代表的数值不相等,同样(11.101)
8
与(11.101)
2
不等价。
十六进制的基本组成是:
表示数的基本符号有十六个,0∽9的数字符号和A∽F的字母符号。字母A∽F分别代表数10∽15;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢十六进一”;
基本运算(不予讨论)。
57A8、1101、1370、901B、FFFF、E.D1C和0.ABC等都是合法的十六进制数字串,而A12H、BE.12.3、A+1F等都不是合法的十六进制数串。(1101)
16
和(1101)
2
代表不同数值。
二进制数与八进制数以及二进制数与十六进制数之间有一种直接的对应关系。一位八进制能表示0∽7之间的8个数值,恰好对应3位二进制能表示的数值范围;一位十六进制表示0∽15之间的16个数值,恰好对应4位二进制能表示的数值范围。用这种对应关系可推导出它们之间的转换方法,其中二进制到八进制(或十六进制)的转换方法称为“三位压缩成一位”(或“四位压缩成一位”),八进制(或十六进制)到二进制之间的转换方法称为“一位展开成三位”(或“一位展开成四位”)。
此处详细介绍二进制与八进制之间的转换方法。对于二进制与十六进制之间的转换,其方法与二进制与八进制之间的转换类似,只要将其中的“三”字换成“四”即可。
二进制到八进制的转换分两个步骤进行,第一步转换数值的整数部分,第二步转换数值的小数部分。
对于整数部分,按照三位一组,从右至左逐步将二进制数字字符分组。如果最左边的一组二进制串不够三位,最高位填充0,直到该组包含三位二进制数字。对于每组的三位二进制数字串表示的数,用对应的八进制数字字符替换之,就得到了整数部分的八进制表示;
对于小数部分,按照三位一组,从左至右逐步将二进制数字字符分组。如果最右边一组的二进制数字不够三位,最低位填充0,直到该组包含三位二进制数字。同样,对于每组的三位二进制数字串表示的数,用等价的八进制数字字符替换之,就得到了小数部分的八进制表示。将这两部的结果合并起来,小数点的位置保持不变,就产生了与该二进制数等价的八进制表示。
下面的连等式显示了将二进制数(1010010101.10111)
2
转换为等价八进制数的过程:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.101110)
2
=(1225.56)
8
类似地,可得到该二进制数的十六进制表示:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.10111000)
2
=(295.B8)
16
从八进制到二进制的转换很简单,只需将八进制数的每个字符代表的数值用对应的三位二进制字符串替代,并且小数点位置不变。转换后高位0和低位0可以省略。例如,将八进制数(3745)
8
转换为对应的二进制数的过程如下:
(3705.426)
8
=(011111000101.100010110)
2
=(11111000101.10001011)
2
用类似方法,能将十六进制数(1F59.A28)
16
转换成对应的二进制表示:
(1F59.A28)
16
=(0001111101011001.101000101000)
2
=(1111101011001.101000101)
2
编程要求
本关的编程任务是补全12-1.py文件中的dec2bin_Int、dec2bin_Point以及bin2oh函数,以实现“任务描述”中的三个题目。
具体请参见后续测试样例。
本关涉及的代码文件12-1.py的代码框架如下:
from random import *
#第一题
def dec2bin_Int(dec):
binum = ''
# 请在此添加代码,补全函数dec2bin_Int
#-----------Begin----------
#------------End-----------
return binum[::-1]
#第二题
def dec2bin_Point(dec, length):
binum = ''
# 请在此添加代码,补全函数dec2bin_Point
#-----------Begin----------
#------------End-----------
return '0.'+binum
#第三题
def bin2oh(binum, oh):
result = ''
if oh == 'o':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
elif oh == 'h':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
if __name__ == '__main__':
seed(0)
tests = [randint(1, n) for n in [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000]]
bins = []
for num in tests:
binum = dec2bin_Int(num)
print(binum)
bins.append(binum)
print('*'*30)
seed(99)
decimals = []
for i in range(10):
decimals.append(round(random(),3))
print(decimals)
for dec in decimals:
print(dec2bin_Point(dec, 8))
print('*' * 30)
print(tests)
for binum in bins:
print(bin2oh(binum, 'o'))
print('*' * 30)
for binum in bins:
print(bin2oh(binum, 'h'))
测试说明
下面是对平台如何评测你所实现功能的说明及样例测试。本关的测试文件是12-1.py自身。
以下是平台对12-1.py的样例测试集:
测试输入:无输入
预期输出:
111
1110
11
100010
10000011
11111001
110011111
11101011001
100110110101
1111010000001
******************************
[0.404, 0.2, 0.179, 0.248, 0.76, 0.251, 0.383, 0.684, 0.539, 0.938]
0.01100111
0.00110011
0.00101101
0.00111111
0.11000010
0.01000000
0.01100010
0.10101111
0.10001001
0.11110000
******************************
[7, 14, 3, 34, 131, 249, 415, 1881, 2485, 7809]
7
16
3
42
203
371
637
3531
4665
17201
******************************
7
E
3
22
83
F9
19F
759
9B5
1E81任务描述
请编写一个Python程序,实现十进制整数到二进制整数的转换;
请编写一个Python程序,实现十进制小数到二进制小数的转换。请注意,length参数用于指定转换后二进制位数;
请编写一个Python程序,实现二进制整数分别到八进制和十六进制整数的转换。请注意,由参数oh来指定是转成八进制(’o’)还是十六进制(’h’)。
相关知识
一个数值能够用不同进制表示,这些表示之间存在转换关系。计算机使用二进制表示数值,而人类惯用十进制。当将数值输入到计算机中时,必须将十进制转换为二进制,而将计算机中的数值输出时,一般要将其转换为十进制,以便于人阅读和理解。对整数而言,虽然进制不同,但是一个数的不同进制表示在数值上是相等的,因此有:
(N)
10
=a
n
×2
n
+⋯+a
1
×2
1
+a
0
×2
0
(1)
上式等号左边下标10表示用十进制表示整数N。由上式可得,将二进制整数转换为十进制整数,可直接按照等号右边的式子,做十进制的乘法和加法就能完成。例如,二进制整数(10111)
2
可按照上式转换为十进制整数:
1×2
4
+0×2
3
+1×2
2
+1×2
1
+1×2
0
=(23)
10
而十进制整数到二进制整数的转换可采用“除2取余”法,其方法也可由上式推导出来。N代表给定的十进制整数,a
n
、…a
1
、a
0
分别代表需要求出的各位二进制数字。(1)式等号两边同时除以2,等式保持不变。从等式右边可看出,N除以2得到的余数是a
0
,得到的商为a
n
×2
n−1
+⋯+a
2
×2
1
+a
1
,对商再除以2,又得余数a
1
和商a
n
×2
n−2
+⋯+a
3
×2
1
+a
2
,等等,依此进行下去,直到商为0。这个过程中得到的所有余数或为0 或为1,将它们按照求得的顺序的反序拼接在一起,就得到所需要的二进制表示形式。
如下图1给出了将(37)
10
转换成二进制的过程,所得结果为:
(37)
10
=(100101)
2
。
二进制小数与十进制小数之间的转换方法也能通过公式推导出来。如下式所示,其中0.a-1a-2… a-m是二进制小数,下标m可能为无穷大,N是等价的十进制小数,下标m可能为无穷大,N是等价的十进制小数。
(N)
10
=a
−1
×2
−1
+a
−2
×2
−2
++⋯+a
−m
×2
−m
(2)
同样地,将二进制小数转换为十进制小数,可直接按照等号右边的式子,做十进制的除法和加法即可。例如,已知(0.1011)
2
,求其等价的十进制小数,转换过程为:
1×2
−1
+0×2
−2
+1×2
−3
+1×2
−4
=(0.6875)
10
十进制小数到二进制小数的转换可采用“乘2取整”法,将公式(2)两边同时乘以2,等式仍成立,此时,右边整数部分变成a
−1
,小数部分变为:
a
−2
×2
−1
+a
−3
×2
−2
+⋯+a
−m
×2
−m+1
再对结果的小数部分两边乘以2,右边整数部分变成a
−2
,小数部分为:
a
−3
×2
−1
+⋯+a
−m
×2
−m+2
依此进行下去,直到乘2的结果中小数部分为0,或者达到所需要的二进制位数。对于很多十进制小数,上述乘2的过程,达不到结果小数部分为0的情形。因此,十进制小数到二进制小数的转换是不精确的转换。下图2中给出了十进制小数到二进制小数转换的两个例子,左边是将十进制数0.625转换成二进制数,它是精确转换;右边是将十进制数0.34转换成二进制数,它是不精确转换。从图中可得:
从图2的例子还可知道,用二进制来表示十进制数时,有些数不能精确表示,只能在表示能力范围内给出近似表示。这与可用的二进制位数和十进制数自身相关:
可用的二进制位数是由计算机的能力决定的,对32位计算机,可以用来表示数的位数通常有8、16和32位,位数越多,能表示的数值越多,精度也越高;
对不能精确转化为二进制的十进制小数,即便能用的二进制位数很多,也无法精确地表示出来。例如,0.1这个十进制小数转换成二进制小数是一个无限循环小数,理论上就无法精确表示。
除了表示数值,还需表示数值的符号: 如“+”或“-”。通常用二进制表示的最高位来表示数值的符号位,0表示正数、1表示负数。因此,如果能用的二进制位为8位,那么,(23)
10
=(00010111)
2
。
而(−23)
10
=(10010111)
2
,这种表示方式称为原码表示。
计算机中通常用浮点数来表示实数,浮点数是指有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意的某个实数。浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。考察下面的Python语句:
>>>print(0.1)
0.1
>>>print("%.17lf" % 0.1)
0.10000000000000001
0.1这个十进制小数转换成二进制数时,是一个无限循环小数,在计算机中通常用浮点数表示,是一种近似的表示。而现代程序设计语言的输出带有一定的智能,在保证误差较小的前提下会自动舍入。所以第一个print语句打印0.1。但是,当用第2个print语句指定输出精度时,就能看到0.1在计算机中不是真正的0.1,而是有一定的误差的。同理,浮点数之间用>、<、==来比较大小是不可取的,需要看两个浮点数是否在合理的误差范围,如果误差合理,即认为相等;否则,两个在十进制中相等的数可能在计算机中是不相等的。
此外,浮点数的误差会在其计算过程中累积,考察下面的Python程序:
x = 0.0
for i in range(100):
x += 0.1
print("%.17lf" % x)
print(x)
运行该程序得到的输出如下所示:第1行是x的较为精确的表示,而第2行是print自动舍入,显示出来的看似正确的结果。
9.99999999999998046
10.0
八进制和十六进制是计算机领域使用的辅助计数法,用于计算机与人类的交互。八进制或十六进制与二进制之间的转换很直观和简单,在认知上接近二进制。这些原因促进人们引入八进制和十六进制。由于这两种进制是辅助计数方法,人们不关心对八进制数或十六进制数的运算,在此对八进制运算和十六进制的运算不进行讨论。
八进制的基本组成为:
基本数字符号有八个,分别是0、1、2、3、4、5、6、7;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢八进一”;
基本运算(不予讨论)。
2374、101、0.564、3.21和11.101等都是合法的八进制数表示,而9021、11.2.5和76+2等都不是合法的八进制数字串。注意八进制串(101)
8
代表的数值与二进制串(101)
2
代表的数值不相等,同样(11.101)
8
与(11.101)
2
不等价。
十六进制的基本组成是:
表示数的基本符号有十六个,0∽9的数字符号和A∽F的字母符号。字母A∽F分别代表数10∽15;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢十六进一”;
基本运算(不予讨论)。
57A8、1101、1370、901B、FFFF、E.D1C和0.ABC等都是合法的十六进制数字串,而A12H、BE.12.3、A+1F等都不是合法的十六进制数串。(1101)
16
和(1101)
2
代表不同数值。
二进制数与八进制数以及二进制数与十六进制数之间有一种直接的对应关系。一位八进制能表示0∽7之间的8个数值,恰好对应3位二进制能表示的数值范围;一位十六进制表示0∽15之间的16个数值,恰好对应4位二进制能表示的数值范围。用这种对应关系可推导出它们之间的转换方法,其中二进制到八进制(或十六进制)的转换方法称为“三位压缩成一位”(或“四位压缩成一位”),八进制(或十六进制)到二进制之间的转换方法称为“一位展开成三位”(或“一位展开成四位”)。
此处详细介绍二进制与八进制之间的转换方法。对于二进制与十六进制之间的转换,其方法与二进制与八进制之间的转换类似,只要将其中的“三”字换成“四”即可。
二进制到八进制的转换分两个步骤进行,第一步转换数值的整数部分,第二步转换数值的小数部分。
对于整数部分,按照三位一组,从右至左逐步将二进制数字字符分组。如果最左边的一组二进制串不够三位,最高位填充0,直到该组包含三位二进制数字。对于每组的三位二进制数字串表示的数,用对应的八进制数字字符替换之,就得到了整数部分的八进制表示;
对于小数部分,按照三位一组,从左至右逐步将二进制数字字符分组。如果最右边一组的二进制数字不够三位,最低位填充0,直到该组包含三位二进制数字。同样,对于每组的三位二进制数字串表示的数,用等价的八进制数字字符替换之,就得到了小数部分的八进制表示。将这两部的结果合并起来,小数点的位置保持不变,就产生了与该二进制数等价的八进制表示。
下面的连等式显示了将二进制数(1010010101.10111)
2
转换为等价八进制数的过程:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.101110)
2
=(1225.56)
8
类似地,可得到该二进制数的十六进制表示:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.10111000)
2
=(295.B8)
16
从八进制到二进制的转换很简单,只需将八进制数的每个字符代表的数值用对应的三位二进制字符串替代,并且小数点位置不变。转换后高位0和低位0可以省略。例如,将八进制数(3745)
8
转换为对应的二进制数的过程如下:
(3705.426)
8
=(011111000101.100010110)
2
=(11111000101.10001011)
2
用类似方法,能将十六进制数(1F59.A28)
16
转换成对应的二进制表示:
(1F59.A28)
16
=(0001111101011001.101000101000)
2
=(1111101011001.101000101)
2
编程要求
本关的编程任务是补全12-1.py文件中的dec2bin_Int、dec2bin_Point以及bin2oh函数,以实现“任务描述”中的三个题目。
具体请参见后续测试样例。
本关涉及的代码文件12-1.py的代码框架如下:
from random import *
#第一题
def dec2bin_Int(dec):
binum = ''
# 请在此添加代码,补全函数dec2bin_Int
#-----------Begin----------
#------------End-----------
return binum[::-1]
#第二题
def dec2bin_Point(dec, length):
binum = ''
# 请在此添加代码,补全函数dec2bin_Point
#-----------Begin----------
#------------End-----------
return '0.'+binum
#第三题
def bin2oh(binum, oh):
result = ''
if oh == 'o':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
elif oh == 'h':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
if __name__ == '__main__':
seed(0)
tests = [randint(1, n) for n in [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000]]
bins = []
for num in tests:
binum = dec2bin_Int(num)
print(binum)
bins.append(binum)
print('*'*30)
seed(99)
decimals = []
for i in range(10):
decimals.append(round(random(),3))
print(decimals)
for dec in decimals:
print(dec2bin_Point(dec, 8))
print('*' * 30)
print(tests)
for binum in bins:
print(bin2oh(binum, 'o'))
print('*' * 30)
for binum in bins:
print(bin2oh(binum, 'h'))
测试说明
下面是对平台如何评测你所实现功能的说明及样例测试。本关的测试文件是12-1.py自身。
以下是平台对12-1.py的样例测试集:
测试输入:无输入
预期输出:
111
1110
11
100010
10000011
11111001
110011111
11101011001
100110110101
1111010000001
******************************
[0.404, 0.2, 0.179, 0.248, 0.76, 0.251, 0.383, 0.684, 0.539, 0.938]
0.01100111
0.00110011
0.00101101
0.00111111
0.11000010
0.01000000
0.01100010
0.10101111
0.10001001
0.11110000
******************************
[7, 14, 3, 34, 131, 249, 415, 1881, 2485, 7809]
7
16
3
42
203
371
637
3531
4665
17201
******************************
7
E
3
22
83
F9
19F
759
9B5
1E81任务描述
请编写一个Python程序,实现十进制整数到二进制整数的转换;
请编写一个Python程序,实现十进制小数到二进制小数的转换。请注意,length参数用于指定转换后二进制位数;
请编写一个Python程序,实现二进制整数分别到八进制和十六进制整数的转换。请注意,由参数oh来指定是转成八进制(’o’)还是十六进制(’h’)。
相关知识
一个数值能够用不同进制表示,这些表示之间存在转换关系。计算机使用二进制表示数值,而人类惯用十进制。当将数值输入到计算机中时,必须将十进制转换为二进制,而将计算机中的数值输出时,一般要将其转换为十进制,以便于人阅读和理解。对整数而言,虽然进制不同,但是一个数的不同进制表示在数值上是相等的,因此有:
(N)
10
=a
n
×2
n
+⋯+a
1
×2
1
+a
0
×2
0
(1)
上式等号左边下标10表示用十进制表示整数N。由上式可得,将二进制整数转换为十进制整数,可直接按照等号右边的式子,做十进制的乘法和加法就能完成。例如,二进制整数(10111)
2
可按照上式转换为十进制整数:
1×2
4
+0×2
3
+1×2
2
+1×2
1
+1×2
0
=(23)
10
而十进制整数到二进制整数的转换可采用“除2取余”法,其方法也可由上式推导出来。N代表给定的十进制整数,a
n
、…a
1
、a
0
分别代表需要求出的各位二进制数字。(1)式等号两边同时除以2,等式保持不变。从等式右边可看出,N除以2得到的余数是a
0
,得到的商为a
n
×2
n−1
+⋯+a
2
×2
1
+a
1
,对商再除以2,又得余数a
1
和商a
n
×2
n−2
+⋯+a
3
×2
1
+a
2
,等等,依此进行下去,直到商为0。这个过程中得到的所有余数或为0 或为1,将它们按照求得的顺序的反序拼接在一起,就得到所需要的二进制表示形式。
如下图1给出了将(37)
10
转换成二进制的过程,所得结果为:
(37)
10
=(100101)
2
。
二进制小数与十进制小数之间的转换方法也能通过公式推导出来。如下式所示,其中0.a-1a-2… a-m是二进制小数,下标m可能为无穷大,N是等价的十进制小数,下标m可能为无穷大,N是等价的十进制小数。
(N)
10
=a
−1
×2
−1
+a
−2
×2
−2
++⋯+a
−m
×2
−m
(2)
同样地,将二进制小数转换为十进制小数,可直接按照等号右边的式子,做十进制的除法和加法即可。例如,已知(0.1011)
2
,求其等价的十进制小数,转换过程为:
1×2
−1
+0×2
−2
+1×2
−3
+1×2
−4
=(0.6875)
10
十进制小数到二进制小数的转换可采用“乘2取整”法,将公式(2)两边同时乘以2,等式仍成立,此时,右边整数部分变成a
−1
,小数部分变为:
a
−2
×2
−1
+a
−3
×2
−2
+⋯+a
−m
×2
−m+1
再对结果的小数部分两边乘以2,右边整数部分变成a
−2
,小数部分为:
a
−3
×2
−1
+⋯+a
−m
×2
−m+2
依此进行下去,直到乘2的结果中小数部分为0,或者达到所需要的二进制位数。对于很多十进制小数,上述乘2的过程,达不到结果小数部分为0的情形。因此,十进制小数到二进制小数的转换是不精确的转换。下图2中给出了十进制小数到二进制小数转换的两个例子,左边是将十进制数0.625转换成二进制数,它是精确转换;右边是将十进制数0.34转换成二进制数,它是不精确转换。从图中可得:
从图2的例子还可知道,用二进制来表示十进制数时,有些数不能精确表示,只能在表示能力范围内给出近似表示。这与可用的二进制位数和十进制数自身相关:
可用的二进制位数是由计算机的能力决定的,对32位计算机,可以用来表示数的位数通常有8、16和32位,位数越多,能表示的数值越多,精度也越高;
对不能精确转化为二进制的十进制小数,即便能用的二进制位数很多,也无法精确地表示出来。例如,0.1这个十进制小数转换成二进制小数是一个无限循环小数,理论上就无法精确表示。
除了表示数值,还需表示数值的符号: 如“+”或“-”。通常用二进制表示的最高位来表示数值的符号位,0表示正数、1表示负数。因此,如果能用的二进制位为8位,那么,(23)
10
=(00010111)
2
。
而(−23)
10
=(10010111)
2
,这种表示方式称为原码表示。
计算机中通常用浮点数来表示实数,浮点数是指有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意的某个实数。浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。考察下面的Python语句:
>>>print(0.1)
0.1
>>>print("%.17lf" % 0.1)
0.10000000000000001
0.1这个十进制小数转换成二进制数时,是一个无限循环小数,在计算机中通常用浮点数表示,是一种近似的表示。而现代程序设计语言的输出带有一定的智能,在保证误差较小的前提下会自动舍入。所以第一个print语句打印0.1。但是,当用第2个print语句指定输出精度时,就能看到0.1在计算机中不是真正的0.1,而是有一定的误差的。同理,浮点数之间用>、<、==来比较大小是不可取的,需要看两个浮点数是否在合理的误差范围,如果误差合理,即认为相等;否则,两个在十进制中相等的数可能在计算机中是不相等的。
此外,浮点数的误差会在其计算过程中累积,考察下面的Python程序:
x = 0.0
for i in range(100):
x += 0.1
print("%.17lf" % x)
print(x)
运行该程序得到的输出如下所示:第1行是x的较为精确的表示,而第2行是print自动舍入,显示出来的看似正确的结果。
9.99999999999998046
10.0
八进制和十六进制是计算机领域使用的辅助计数法,用于计算机与人类的交互。八进制或十六进制与二进制之间的转换很直观和简单,在认知上接近二进制。这些原因促进人们引入八进制和十六进制。由于这两种进制是辅助计数方法,人们不关心对八进制数或十六进制数的运算,在此对八进制运算和十六进制的运算不进行讨论。
八进制的基本组成为:
基本数字符号有八个,分别是0、1、2、3、4、5、6、7;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢八进一”;
基本运算(不予讨论)。
2374、101、0.564、3.21和11.101等都是合法的八进制数表示,而9021、11.2.5和76+2等都不是合法的八进制数字串。注意八进制串(101)
8
代表的数值与二进制串(101)
2
代表的数值不相等,同样(11.101)
8
与(11.101)
2
不等价。
十六进制的基本组成是:
表示数的基本符号有十六个,0∽9的数字符号和A∽F的字母符号。字母A∽F分别代表数10∽15;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢十六进一”;
基本运算(不予讨论)。
57A8、1101、1370、901B、FFFF、E.D1C和0.ABC等都是合法的十六进制数字串,而A12H、BE.12.3、A+1F等都不是合法的十六进制数串。(1101)
16
和(1101)
2
代表不同数值。
二进制数与八进制数以及二进制数与十六进制数之间有一种直接的对应关系。一位八进制能表示0∽7之间的8个数值,恰好对应3位二进制能表示的数值范围;一位十六进制表示0∽15之间的16个数值,恰好对应4位二进制能表示的数值范围。用这种对应关系可推导出它们之间的转换方法,其中二进制到八进制(或十六进制)的转换方法称为“三位压缩成一位”(或“四位压缩成一位”),八进制(或十六进制)到二进制之间的转换方法称为“一位展开成三位”(或“一位展开成四位”)。
此处详细介绍二进制与八进制之间的转换方法。对于二进制与十六进制之间的转换,其方法与二进制与八进制之间的转换类似,只要将其中的“三”字换成“四”即可。
二进制到八进制的转换分两个步骤进行,第一步转换数值的整数部分,第二步转换数值的小数部分。
对于整数部分,按照三位一组,从右至左逐步将二进制数字字符分组。如果最左边的一组二进制串不够三位,最高位填充0,直到该组包含三位二进制数字。对于每组的三位二进制数字串表示的数,用对应的八进制数字字符替换之,就得到了整数部分的八进制表示;
对于小数部分,按照三位一组,从左至右逐步将二进制数字字符分组。如果最右边一组的二进制数字不够三位,最低位填充0,直到该组包含三位二进制数字。同样,对于每组的三位二进制数字串表示的数,用等价的八进制数字字符替换之,就得到了小数部分的八进制表示。将这两部的结果合并起来,小数点的位置保持不变,就产生了与该二进制数等价的八进制表示。
下面的连等式显示了将二进制数(1010010101.10111)
2
转换为等价八进制数的过程:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.101110)
2
=(1225.56)
8
类似地,可得到该二进制数的十六进制表示:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.10111000)
2
=(295.B8)
16
从八进制到二进制的转换很简单,只需将八进制数的每个字符代表的数值用对应的三位二进制字符串替代,并且小数点位置不变。转换后高位0和低位0可以省略。例如,将八进制数(3745)
8
转换为对应的二进制数的过程如下:
(3705.426)
8
=(011111000101.100010110)
2
=(11111000101.10001011)
2
用类似方法,能将十六进制数(1F59.A28)
16
转换成对应的二进制表示:
(1F59.A28)
16
=(0001111101011001.101000101000)
2
=(1111101011001.101000101)
2
编程要求
本关的编程任务是补全12-1.py文件中的dec2bin_Int、dec2bin_Point以及bin2oh函数,以实现“任务描述”中的三个题目。
具体请参见后续测试样例。
本关涉及的代码文件12-1.py的代码框架如下:
from random import *
#第一题
def dec2bin_Int(dec):
binum = ''
# 请在此添加代码,补全函数dec2bin_Int
#-----------Begin----------
#------------End-----------
return binum[::-1]
#第二题
def dec2bin_Point(dec, length):
binum = ''
# 请在此添加代码,补全函数dec2bin_Point
#-----------Begin----------
#------------End-----------
return '0.'+binum
#第三题
def bin2oh(binum, oh):
result = ''
if oh == 'o':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
elif oh == 'h':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
if __name__ == '__main__':
seed(0)
tests = [randint(1, n) for n in [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000]]
bins = []
for num in tests:
binum = dec2bin_Int(num)
print(binum)
bins.append(binum)
print('*'*30)
seed(99)
decimals = []
for i in range(10):
decimals.append(round(random(),3))
print(decimals)
for dec in decimals:
print(dec2bin_Point(dec, 8))
print('*' * 30)
print(tests)
for binum in bins:
print(bin2oh(binum, 'o'))
print('*' * 30)
for binum in bins:
print(bin2oh(binum, 'h'))
测试说明
下面是对平台如何评测你所实现功能的说明及样例测试。本关的测试文件是12-1.py自身。
以下是平台对12-1.py的样例测试集:
测试输入:无输入
预期输出:
111
1110
11
100010
10000011
11111001
110011111
11101011001
100110110101
1111010000001
******************************
[0.404, 0.2, 0.179, 0.248, 0.76, 0.251, 0.383, 0.684, 0.539, 0.938]
0.01100111
0.00110011
0.00101101
0.00111111
0.11000010
0.01000000
0.01100010
0.10101111
0.10001001
0.11110000
******************************
[7, 14, 3, 34, 131, 249, 415, 1881, 2485, 7809]
7
16
3
42
203
371
637
3531
4665
17201
******************************
7
E
3
22
83
F9
19F
759
9B5
1E81任务描述
请编写一个Python程序,实现十进制整数到二进制整数的转换;
请编写一个Python程序,实现十进制小数到二进制小数的转换。请注意,length参数用于指定转换后二进制位数;
请编写一个Python程序,实现二进制整数分别到八进制和十六进制整数的转换。请注意,由参数oh来指定是转成八进制(’o’)还是十六进制(’h’)。
相关知识
一个数值能够用不同进制表示,这些表示之间存在转换关系。计算机使用二进制表示数值,而人类惯用十进制。当将数值输入到计算机中时,必须将十进制转换为二进制,而将计算机中的数值输出时,一般要将其转换为十进制,以便于人阅读和理解。对整数而言,虽然进制不同,但是一个数的不同进制表示在数值上是相等的,因此有:
(N)
10
=a
n
×2
n
+⋯+a
1
×2
1
+a
0
×2
0
(1)
上式等号左边下标10表示用十进制表示整数N。由上式可得,将二进制整数转换为十进制整数,可直接按照等号右边的式子,做十进制的乘法和加法就能完成。例如,二进制整数(10111)
2
可按照上式转换为十进制整数:
1×2
4
+0×2
3
+1×2
2
+1×2
1
+1×2
0
=(23)
10
而十进制整数到二进制整数的转换可采用“除2取余”法,其方法也可由上式推导出来。N代表给定的十进制整数,a
n
、…a
1
、a
0
分别代表需要求出的各位二进制数字。(1)式等号两边同时除以2,等式保持不变。从等式右边可看出,N除以2得到的余数是a
0
,得到的商为a
n
×2
n−1
+⋯+a
2
×2
1
+a
1
,对商再除以2,又得余数a
1
和商a
n
×2
n−2
+⋯+a
3
×2
1
+a
2
,等等,依此进行下去,直到商为0。这个过程中得到的所有余数或为0 或为1,将它们按照求得的顺序的反序拼接在一起,就得到所需要的二进制表示形式。
如下图1给出了将(37)
10
转换成二进制的过程,所得结果为:
(37)
10
=(100101)
2
。
二进制小数与十进制小数之间的转换方法也能通过公式推导出来。如下式所示,其中0.a-1a-2… a-m是二进制小数,下标m可能为无穷大,N是等价的十进制小数,下标m可能为无穷大,N是等价的十进制小数。
(N)
10
=a
−1
×2
−1
+a
−2
×2
−2
++⋯+a
−m
×2
−m
(2)
同样地,将二进制小数转换为十进制小数,可直接按照等号右边的式子,做十进制的除法和加法即可。例如,已知(0.1011)
2
,求其等价的十进制小数,转换过程为:
1×2
−1
+0×2
−2
+1×2
−3
+1×2
−4
=(0.6875)
10
十进制小数到二进制小数的转换可采用“乘2取整”法,将公式(2)两边同时乘以2,等式仍成立,此时,右边整数部分变成a
−1
,小数部分变为:
a
−2
×2
−1
+a
−3
×2
−2
+⋯+a
−m
×2
−m+1
再对结果的小数部分两边乘以2,右边整数部分变成a
−2
,小数部分为:
a
−3
×2
−1
+⋯+a
−m
×2
−m+2
依此进行下去,直到乘2的结果中小数部分为0,或者达到所需要的二进制位数。对于很多十进制小数,上述乘2的过程,达不到结果小数部分为0的情形。因此,十进制小数到二进制小数的转换是不精确的转换。下图2中给出了十进制小数到二进制小数转换的两个例子,左边是将十进制数0.625转换成二进制数,它是精确转换;右边是将十进制数0.34转换成二进制数,它是不精确转换。从图中可得:
从图2的例子还可知道,用二进制来表示十进制数时,有些数不能精确表示,只能在表示能力范围内给出近似表示。这与可用的二进制位数和十进制数自身相关:
可用的二进制位数是由计算机的能力决定的,对32位计算机,可以用来表示数的位数通常有8、16和32位,位数越多,能表示的数值越多,精度也越高;
对不能精确转化为二进制的十进制小数,即便能用的二进制位数很多,也无法精确地表示出来。例如,0.1这个十进制小数转换成二进制小数是一个无限循环小数,理论上就无法精确表示。
除了表示数值,还需表示数值的符号: 如“+”或“-”。通常用二进制表示的最高位来表示数值的符号位,0表示正数、1表示负数。因此,如果能用的二进制位为8位,那么,(23)
10
=(00010111)
2
。
而(−23)
10
=(10010111)
2
,这种表示方式称为原码表示。
计算机中通常用浮点数来表示实数,浮点数是指有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意的某个实数。浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。考察下面的Python语句:
>>>print(0.1)
0.1
>>>print("%.17lf" % 0.1)
0.10000000000000001
0.1这个十进制小数转换成二进制数时,是一个无限循环小数,在计算机中通常用浮点数表示,是一种近似的表示。而现代程序设计语言的输出带有一定的智能,在保证误差较小的前提下会自动舍入。所以第一个print语句打印0.1。但是,当用第2个print语句指定输出精度时,就能看到0.1在计算机中不是真正的0.1,而是有一定的误差的。同理,浮点数之间用>、<、==来比较大小是不可取的,需要看两个浮点数是否在合理的误差范围,如果误差合理,即认为相等;否则,两个在十进制中相等的数可能在计算机中是不相等的。
此外,浮点数的误差会在其计算过程中累积,考察下面的Python程序:
x = 0.0
for i in range(100):
x += 0.1
print("%.17lf" % x)
print(x)
运行该程序得到的输出如下所示:第1行是x的较为精确的表示,而第2行是print自动舍入,显示出来的看似正确的结果。
9.99999999999998046
10.0
八进制和十六进制是计算机领域使用的辅助计数法,用于计算机与人类的交互。八进制或十六进制与二进制之间的转换很直观和简单,在认知上接近二进制。这些原因促进人们引入八进制和十六进制。由于这两种进制是辅助计数方法,人们不关心对八进制数或十六进制数的运算,在此对八进制运算和十六进制的运算不进行讨论。
八进制的基本组成为:
基本数字符号有八个,分别是0、1、2、3、4、5、6、7;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢八进一”;
基本运算(不予讨论)。
2374、101、0.564、3.21和11.101等都是合法的八进制数表示,而9021、11.2.5和76+2等都不是合法的八进制数字串。注意八进制串(101)
8
代表的数值与二进制串(101)
2
代表的数值不相等,同样(11.101)
8
与(11.101)
2
不等价。
十六进制的基本组成是:
表示数的基本符号有十六个,0∽9的数字符号和A∽F的字母符号。字母A∽F分别代表数10∽15;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢十六进一”;
基本运算(不予讨论)。
57A8、1101、1370、901B、FFFF、E.D1C和0.ABC等都是合法的十六进制数字串,而A12H、BE.12.3、A+1F等都不是合法的十六进制数串。(1101)
16
和(1101)
2
代表不同数值。
二进制数与八进制数以及二进制数与十六进制数之间有一种直接的对应关系。一位八进制能表示0∽7之间的8个数值,恰好对应3位二进制能表示的数值范围;一位十六进制表示0∽15之间的16个数值,恰好对应4位二进制能表示的数值范围。用这种对应关系可推导出它们之间的转换方法,其中二进制到八进制(或十六进制)的转换方法称为“三位压缩成一位”(或“四位压缩成一位”),八进制(或十六进制)到二进制之间的转换方法称为“一位展开成三位”(或“一位展开成四位”)。
此处详细介绍二进制与八进制之间的转换方法。对于二进制与十六进制之间的转换,其方法与二进制与八进制之间的转换类似,只要将其中的“三”字换成“四”即可。
二进制到八进制的转换分两个步骤进行,第一步转换数值的整数部分,第二步转换数值的小数部分。
对于整数部分,按照三位一组,从右至左逐步将二进制数字字符分组。如果最左边的一组二进制串不够三位,最高位填充0,直到该组包含三位二进制数字。对于每组的三位二进制数字串表示的数,用对应的八进制数字字符替换之,就得到了整数部分的八进制表示;
对于小数部分,按照三位一组,从左至右逐步将二进制数字字符分组。如果最右边一组的二进制数字不够三位,最低位填充0,直到该组包含三位二进制数字。同样,对于每组的三位二进制数字串表示的数,用等价的八进制数字字符替换之,就得到了小数部分的八进制表示。将这两部的结果合并起来,小数点的位置保持不变,就产生了与该二进制数等价的八进制表示。
下面的连等式显示了将二进制数(1010010101.10111)
2
转换为等价八进制数的过程:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.101110)
2
=(1225.56)
8
类似地,可得到该二进制数的十六进制表示:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.10111000)
2
=(295.B8)
16
从八进制到二进制的转换很简单,只需将八进制数的每个字符代表的数值用对应的三位二进制字符串替代,并且小数点位置不变。转换后高位0和低位0可以省略。例如,将八进制数(3745)
8
转换为对应的二进制数的过程如下:
(3705.426)
8
=(011111000101.100010110)
2
=(11111000101.10001011)
2
用类似方法,能将十六进制数(1F59.A28)
16
转换成对应的二进制表示:
(1F59.A28)
16
=(0001111101011001.101000101000)
2
=(1111101011001.101000101)
2
编程要求
本关的编程任务是补全12-1.py文件中的dec2bin_Int、dec2bin_Point以及bin2oh函数,以实现“任务描述”中的三个题目。
具体请参见后续测试样例。
本关涉及的代码文件12-1.py的代码框架如下:
from random import *
#第一题
def dec2bin_Int(dec):
binum = ''
# 请在此添加代码,补全函数dec2bin_Int
#-----------Begin----------
#------------End-----------
return binum[::-1]
#第二题
def dec2bin_Point(dec, length):
binum = ''
# 请在此添加代码,补全函数dec2bin_Point
#-----------Begin----------
#------------End-----------
return '0.'+binum
#第三题
def bin2oh(binum, oh):
result = ''
if oh == 'o':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
elif oh == 'h':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
if __name__ == '__main__':
seed(0)
tests = [randint(1, n) for n in [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000]]
bins = []
for num in tests:
binum = dec2bin_Int(num)
print(binum)
bins.append(binum)
print('*'*30)
seed(99)
decimals = []
for i in range(10):
decimals.append(round(random(),3))
print(decimals)
for dec in decimals:
print(dec2bin_Point(dec, 8))
print('*' * 30)
print(tests)
for binum in bins:
print(bin2oh(binum, 'o'))
print('*' * 30)
for binum in bins:
print(bin2oh(binum, 'h'))
测试说明
下面是对平台如何评测你所实现功能的说明及样例测试。本关的测试文件是12-1.py自身。
以下是平台对12-1.py的样例测试集:
测试输入:无输入
预期输出:
111
1110
11
100010
10000011
11111001
110011111
11101011001
100110110101
1111010000001
******************************
[0.404, 0.2, 0.179, 0.248, 0.76, 0.251, 0.383, 0.684, 0.539, 0.938]
0.01100111
0.00110011
0.00101101
0.00111111
0.11000010
0.01000000
0.01100010
0.10101111
0.10001001
0.11110000
******************************
[7, 14, 3, 34, 131, 249, 415, 1881, 2485, 7809]
7
16
3
42
203
371
637
3531
4665
17201
******************************
7
E
3
22
83
F9
19F
759
9B5
1E81任务描述
请编写一个Python程序,实现十进制整数到二进制整数的转换;
请编写一个Python程序,实现十进制小数到二进制小数的转换。请注意,length参数用于指定转换后二进制位数;
请编写一个Python程序,实现二进制整数分别到八进制和十六进制整数的转换。请注意,由参数oh来指定是转成八进制(’o’)还是十六进制(’h’)。
相关知识
一个数值能够用不同进制表示,这些表示之间存在转换关系。计算机使用二进制表示数值,而人类惯用十进制。当将数值输入到计算机中时,必须将十进制转换为二进制,而将计算机中的数值输出时,一般要将其转换为十进制,以便于人阅读和理解。对整数而言,虽然进制不同,但是一个数的不同进制表示在数值上是相等的,因此有:
(N)
10
=a
n
×2
n
+⋯+a
1
×2
1
+a
0
×2
0
(1)
上式等号左边下标10表示用十进制表示整数N。由上式可得,将二进制整数转换为十进制整数,可直接按照等号右边的式子,做十进制的乘法和加法就能完成。例如,二进制整数(10111)
2
可按照上式转换为十进制整数:
1×2
4
+0×2
3
+1×2
2
+1×2
1
+1×2
0
=(23)
10
而十进制整数到二进制整数的转换可采用“除2取余”法,其方法也可由上式推导出来。N代表给定的十进制整数,a
n
、…a
1
、a
0
分别代表需要求出的各位二进制数字。(1)式等号两边同时除以2,等式保持不变。从等式右边可看出,N除以2得到的余数是a
0
,得到的商为a
n
×2
n−1
+⋯+a
2
×2
1
+a
1
,对商再除以2,又得余数a
1
和商a
n
×2
n−2
+⋯+a
3
×2
1
+a
2
,等等,依此进行下去,直到商为0。这个过程中得到的所有余数或为0 或为1,将它们按照求得的顺序的反序拼接在一起,就得到所需要的二进制表示形式。
如下图1给出了将(37)
10
转换成二进制的过程,所得结果为:
(37)
10
=(100101)
2
。
二进制小数与十进制小数之间的转换方法也能通过公式推导出来。如下式所示,其中0.a-1a-2… a-m是二进制小数,下标m可能为无穷大,N是等价的十进制小数,下标m可能为无穷大,N是等价的十进制小数。
(N)
10
=a
−1
×2
−1
+a
−2
×2
−2
++⋯+a
−m
×2
−m
(2)
同样地,将二进制小数转换为十进制小数,可直接按照等号右边的式子,做十进制的除法和加法即可。例如,已知(0.1011)
2
,求其等价的十进制小数,转换过程为:
1×2
−1
+0×2
−2
+1×2
−3
+1×2
−4
=(0.6875)
10
十进制小数到二进制小数的转换可采用“乘2取整”法,将公式(2)两边同时乘以2,等式仍成立,此时,右边整数部分变成a
−1
,小数部分变为:
a
−2
×2
−1
+a
−3
×2
−2
+⋯+a
−m
×2
−m+1
再对结果的小数部分两边乘以2,右边整数部分变成a
−2
,小数部分为:
a
−3
×2
−1
+⋯+a
−m
×2
−m+2
依此进行下去,直到乘2的结果中小数部分为0,或者达到所需要的二进制位数。对于很多十进制小数,上述乘2的过程,达不到结果小数部分为0的情形。因此,十进制小数到二进制小数的转换是不精确的转换。下图2中给出了十进制小数到二进制小数转换的两个例子,左边是将十进制数0.625转换成二进制数,它是精确转换;右边是将十进制数0.34转换成二进制数,它是不精确转换。从图中可得:
从图2的例子还可知道,用二进制来表示十进制数时,有些数不能精确表示,只能在表示能力范围内给出近似表示。这与可用的二进制位数和十进制数自身相关:
可用的二进制位数是由计算机的能力决定的,对32位计算机,可以用来表示数的位数通常有8、16和32位,位数越多,能表示的数值越多,精度也越高;
对不能精确转化为二进制的十进制小数,即便能用的二进制位数很多,也无法精确地表示出来。例如,0.1这个十进制小数转换成二进制小数是一个无限循环小数,理论上就无法精确表示。
除了表示数值,还需表示数值的符号: 如“+”或“-”。通常用二进制表示的最高位来表示数值的符号位,0表示正数、1表示负数。因此,如果能用的二进制位为8位,那么,(23)
10
=(00010111)
2
。
而(−23)
10
=(10010111)
2
,这种表示方式称为原码表示。
计算机中通常用浮点数来表示实数,浮点数是指有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意的某个实数。浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。考察下面的Python语句:
>>>print(0.1)
0.1
>>>print("%.17lf" % 0.1)
0.10000000000000001
0.1这个十进制小数转换成二进制数时,是一个无限循环小数,在计算机中通常用浮点数表示,是一种近似的表示。而现代程序设计语言的输出带有一定的智能,在保证误差较小的前提下会自动舍入。所以第一个print语句打印0.1。但是,当用第2个print语句指定输出精度时,就能看到0.1在计算机中不是真正的0.1,而是有一定的误差的。同理,浮点数之间用>、<、==来比较大小是不可取的,需要看两个浮点数是否在合理的误差范围,如果误差合理,即认为相等;否则,两个在十进制中相等的数可能在计算机中是不相等的。
此外,浮点数的误差会在其计算过程中累积,考察下面的Python程序:
x = 0.0
for i in range(100):
x += 0.1
print("%.17lf" % x)
print(x)
运行该程序得到的输出如下所示:第1行是x的较为精确的表示,而第2行是print自动舍入,显示出来的看似正确的结果。
9.99999999999998046
10.0
八进制和十六进制是计算机领域使用的辅助计数法,用于计算机与人类的交互。八进制或十六进制与二进制之间的转换很直观和简单,在认知上接近二进制。这些原因促进人们引入八进制和十六进制。由于这两种进制是辅助计数方法,人们不关心对八进制数或十六进制数的运算,在此对八进制运算和十六进制的运算不进行讨论。
八进制的基本组成为:
基本数字符号有八个,分别是0、1、2、3、4、5、6、7;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢八进一”;
基本运算(不予讨论)。
2374、101、0.564、3.21和11.101等都是合法的八进制数表示,而9021、11.2.5和76+2等都不是合法的八进制数字串。注意八进制串(101)
8
代表的数值与二进制串(101)
2
代表的数值不相等,同样(11.101)
8
与(11.101)
2
不等价。
十六进制的基本组成是:
表示数的基本符号有十六个,0∽9的数字符号和A∽F的字母符号。字母A∽F分别代表数10∽15;
基本符号形成字符串的语法规则与二进制相同;
解释合法字符串的语义规则是“逢十六进一”;
基本运算(不予讨论)。
57A8、1101、1370、901B、FFFF、E.D1C和0.ABC等都是合法的十六进制数字串,而A12H、BE.12.3、A+1F等都不是合法的十六进制数串。(1101)
16
和(1101)
2
代表不同数值。
二进制数与八进制数以及二进制数与十六进制数之间有一种直接的对应关系。一位八进制能表示0∽7之间的8个数值,恰好对应3位二进制能表示的数值范围;一位十六进制表示0∽15之间的16个数值,恰好对应4位二进制能表示的数值范围。用这种对应关系可推导出它们之间的转换方法,其中二进制到八进制(或十六进制)的转换方法称为“三位压缩成一位”(或“四位压缩成一位”),八进制(或十六进制)到二进制之间的转换方法称为“一位展开成三位”(或“一位展开成四位”)。
此处详细介绍二进制与八进制之间的转换方法。对于二进制与十六进制之间的转换,其方法与二进制与八进制之间的转换类似,只要将其中的“三”字换成“四”即可。
二进制到八进制的转换分两个步骤进行,第一步转换数值的整数部分,第二步转换数值的小数部分。
对于整数部分,按照三位一组,从右至左逐步将二进制数字字符分组。如果最左边的一组二进制串不够三位,最高位填充0,直到该组包含三位二进制数字。对于每组的三位二进制数字串表示的数,用对应的八进制数字字符替换之,就得到了整数部分的八进制表示;
对于小数部分,按照三位一组,从左至右逐步将二进制数字字符分组。如果最右边一组的二进制数字不够三位,最低位填充0,直到该组包含三位二进制数字。同样,对于每组的三位二进制数字串表示的数,用等价的八进制数字字符替换之,就得到了小数部分的八进制表示。将这两部的结果合并起来,小数点的位置保持不变,就产生了与该二进制数等价的八进制表示。
下面的连等式显示了将二进制数(1010010101.10111)
2
转换为等价八进制数的过程:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.101110)
2
=(1225.56)
8
类似地,可得到该二进制数的十六进制表示:
(1010010101.10111)
2
=(1010010101.10111)
2
=(001010010101.10111000)
2
=(295.B8)
16
从八进制到二进制的转换很简单,只需将八进制数的每个字符代表的数值用对应的三位二进制字符串替代,并且小数点位置不变。转换后高位0和低位0可以省略。例如,将八进制数(3745)
8
转换为对应的二进制数的过程如下:
(3705.426)
8
=(011111000101.100010110)
2
=(11111000101.10001011)
2
用类似方法,能将十六进制数(1F59.A28)
16
转换成对应的二进制表示:
(1F59.A28)
16
=(0001111101011001.101000101000)
2
=(1111101011001.101000101)
2
编程要求
本关的编程任务是补全12-1.py文件中的dec2bin_Int、dec2bin_Point以及bin2oh函数,以实现“任务描述”中的三个题目。
具体请参见后续测试样例。
本关涉及的代码文件12-1.py的代码框架如下:
from random import *
#第一题
def dec2bin_Int(dec):
binum = ''
# 请在此添加代码,补全函数dec2bin_Int
#-----------Begin----------
#------------End-----------
return binum[::-1]
#第二题
def dec2bin_Point(dec, length):
binum = ''
# 请在此添加代码,补全函数dec2bin_Point
#-----------Begin----------
#------------End-----------
return '0.'+binum
#第三题
def bin2oh(binum, oh):
result = ''
if oh == 'o':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
elif oh == 'h':
# 请在此添加代码,补全函数bin2oh
#-----------Begin----------
#------------End-----------
return result
if __name__ == '__main__':
seed(0)
tests = [randint(1, n) for n in [10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000]]
bins = []
for num in tests:
binum = dec2bin_Int(num)
print(binum)
bins.append(binum)
print('*'*30)
seed(99)
decimals = []
for i in range(10):
decimals.append(round(random(),3))
print(decimals)
for dec in decimals:
print(dec2bin_Point(dec, 8))
print('*' * 30)
print(tests)
for binum in bins:
print(bin2oh(binum, 'o'))
print('*' * 30)
for binum in bins:
print(bin2oh(binum, 'h'))
测试说明
下面是对平台如何评测你所实现功能的说明及样例测试。本关的测试文件是12-1.py自身。
以下是平台对12-1.py的样例测试集:
测试输入:无输入
预期输出:
111
1110
11
100010
10000011
11111001
110011111
11101011001
100110110101
1111010000001
******************************
[0.404, 0.2, 0.179, 0.248, 0.76, 0.251, 0.383, 0.684, 0.539, 0.938]
0.01100111
0.00110011
0.00101101
0.00111111
0.11000010
0.01000000
0.01100010
0.10101111
0.10001001
0.11110000
******************************
[7, 14, 3, 34, 131, 249, 415, 1881, 2485, 7809]
7
16
3
42
203
371
637
3531
4665
17201
******************************
7
E
3
22
83
F9
19F
759
9B5
1E81
最新发布