庆祝上午论文答辩结束,晚上喊了一行人出去K歌。回来之后大脑就一直处于兴奋状态了,躺在床上满脑子都在回响着《天高地厚》这一首歌,我使劲地想睡也睡不着。既然再怎么“数羊子”都于事无补,索性起来写点东西,顺便把论文中关于数值型数据的存储形式的这一块拿出来做一个总结,更新上博客,方便日后查阅。
论文第四章的2.1小节针对数值型(Numeric)数据在内存中的几种存储形式进行了分析比较,(呵呵,论文上用的词是“分析研究”了,相信大家都明白这是什么意思的)这里得到的东西就是“研究”成果了,也就是毕业论文中的精华所在了。
4.2.1——数值型(Numeric)在内存中的5种存储形式
数值型数据使用9型描述符,一个描述符只允许存储0-9当中的一个数字。数值型数据是COBOL程序中使用得最多的一种数据类型,数值型数据在内存中有5种存储形式,一般用USAGE子句来指定数据项在内存中的存储形式,但是USAGE子句通常可以省略,省略USAGE的条件下默认存储形式为Display类型,它表示该数值型数据在内存中以外部十进制形式存储。
(1)Display:外部十进制形式。表示数值在机器外部的表现形式,一个数字在内存中占一个字节。直接用9型描述符标识, Display关键字可以省略。
(2)COMP:定点二进制形式。这种存储形式不是将一个数字对应一个字节或者半个字节,而是先把十进制数转化成二进制数形式然后在内存中存储。因为机器存储的形式也是二进制,所以采用定点二进制存储形式的数据读取时速度最快的。COMP型数据经常用来做数学计算。COBOL规定在内存中根据数据项的长度分别用两个字节、四个字节或八个字节来存放定点二进制形式的数值。见表1。
表1 COMP型数据项长度与内存字节对应关系
| PIC子句中 描述符’9′的个数 |
占内存空间大小
|
|
1-4
|
2Byte
|
|
5-9
|
4Byte
|
|
10-18
|
8Byte
|
(3)COMP-1、COMP-2:内部浮点数形式。以内部的二进制指数形式来表示一个数,以固定长度的内存单元来存放一个数字。
COMP-1:单精度内部浮点数,默认为4个Byte。4个Byte表示一个数字,8位为指数部分、24位为数字部分。
COMP-2:双精度内部浮点数,默认为8个Byte。8个Byte表示一个数字,16位为指数部分、48位为数字部分。
注意:COMP-1和COMP-2只能使用USAGE子句进行定义,因为长度确定,不能用PIC描述符。
(4)COMP-3:内部压缩十进制。外部十进制形式一个数字在内存中占一个字节。数值型数据只用到0到9十个数字,从表2可以看出,0到9十个数字的代码前四位是相同的,见表2。
表2 外部十进制数EBCDIC编码
| 十进制数字 |
EBCDIC码 |
ASCII码 |
| 0 |
11110000 |
00110000 |
| 1 |
11110001 |
00110001 |
| 2 |
11110010 |
00110010 |
| 3 |
11110011 |
00110011 |
| 4 |
11110100 |
00110100 |
| 5 |
11110101 |
00110101 |
| 6 |
11110110 |
00110110 |
| 7 |
11110111 |
00110111 |
| 8 |
11111000 |
00111000 |
| 9 |
11111001 |
00111001 |
由于前4位都是一样的,不起辨别数值大小的作用,为节省内存,就采用4个二进制位来存储一个十进制数字。在一个字节中存放两个十进制数字,每个数字占半个字节(4位),最后符号也占半个字节(4位)。
对于负数,最后一个半字节(4位)为“1101”,对应16进制为字母D。
对于正数,最后一个半字节(4位)为“1100”,对应16进制为字母C。
对于无符号数,最后一个半字节(4位)为“1111”,对应16进制为字母F。
(5)COMP-5:定点二进制数。COMP-5型和COMP型数据内部存储形式一致,在特定的平台上用到,只不过COMP型数据使用大尾字节顺序存储,COMP-5型数据使用小尾字节顺序存储。不理解大尾字节和小尾字节的猛击这里。
Display型和COMP-3型数据分析比较
在介绍了COBOL语言中5种基本数据类型之后,针对数值型数据中的Display型(外部十进制)和COMP-3型(内部压缩十进制)数据进行分析比较,可以更好地理解数值型数据在计算机内存中的存储形式。详见表3和表4。
表3 Display型数据分析
| 定义类型 |
初始数值 |
输出结果 |
内存16进制存储形式 |
| 9(5)V9(2) |
+12345.67 |
1234567 |
F1F2F3F4F5F6F7 |
| 9(5)V9(2) |
-12345.67 |
1234567 |
F1F2F3F4F5F6F7 |
| S9(5)V92) |
+12345.67 |
123456G |
F1F2F3F4F5F6C7 |
| S9(5)V92) |
-12345.67 |
123456P |
F1F2F3F4F5F6D7 |
(1) 使用Value子句进行赋值(见图3)。

图3 使用Value子句给Display型数据赋初始值
(2)使用Display语句输出结果(见图4)。
(3)使用Write语句写入到文件中的结果(见右图5)。

图4 Display语句输出结果 图5 Write语句输出结果
表4 9型COMP-3数据分析
| 定义类型 |
初始数值 |
输出结果 |
内存16进制存储形式 |
| 9(5)V9(2)COMP-3 |
+12345.67 |
1234567 |
1234567F |
| 9(5)V9(2)COMP-3 |
-12345.67 |
1234567 |
1234567F |
| S9(5)V9(2)COMP-3 |
+12345.67 |
123456G |
1234567C |
| S9(5)V9(2)COMP-3 |
-12345.67 |
123456P |
1234567D |
(1)使用Value子句进行赋值(图6)。

图6 使用Value子句给COMP-3型数据赋初始值
(2)Display语句输出的结果(见下图7)。
(3)Write语句写入到文件中的结果(见右图8)。

图7 Display语句输出结果 图8 Write语句输出结果
根据对比分析的情况得出来如下的结果:
(1)Value子句赋初始值要求数据完全匹配属性要求,9型描述符初始值中不允许出现“+”、“-”符号;Move语句赋初始值则只要求数据类型匹配,在初始值中可以带有“+”、“-”符号。
(2)不管是9型还是S9型描述符,对应Display和COMP-3两种存储形式“+”、“-”都不实际输出显示出来。
(3)对于Display型和COMP-3型存储形式,S9型描述符将符号位存储在最后一个半字节(4位),字母C表示符号为正,D表示符号为负,F表示无符号。
(4)Display型存储形式9型描述符和S9型描述符每一个数字占一个字节内存空间,符号和小数点都不占内存空间。
(5)COMP-3型存储形式由于采用压缩十进制方式存储,每一个数字占半个字节(4位)内存空间,再在最后增加半个字节(4位)存储符号位。因此,同样的数据内容COMP-3型存储比Display型节省内存空间。
(6)Write语句是按内存中存放的数据形式直接输出的,不进行EBCDIC编码[9]转换;Display语句则是将内存中存放的数据形式进行EBCDIC编码转换后然后再进行输出的。因此,写入到输出文件中看到的结果会产生乱码。
欧冠决赛已经开始打响了,国米跟拜仁随便哪只队赢都是三冠王,看球去了,到此为止。