在 COBOL 中使用 COMP 的变量
Posted
技术标签:
【中文标题】在 COBOL 中使用 COMP 的变量【英文标题】:Variable with usage COMP in COBOL 【发布时间】:2017-02-23 09:28:43 【问题描述】:我试图了解带有 COMP Usage 子句的 COBOL 变量如何存储值。
我尝试了一个如下示例
01 VAR14 PIC S9(5) USAGE COMP.
MOVE 12345 TO VAR14
DISPLAY VAR14
在 SPOOL 中,VAR14
的值是 0000012345
。
S9(5) COMP
按照手册的大小是 4 个字节,所以我的理解是 VAR14
应该显示为 000012345
。
二进制表示如下:
0000 0000 0000 0000 0011 0000 0011 0100
有人可以帮助理解0000012345
的输出值吗?
谢谢
【问题讨论】:
正确的二进制:0000 0000 0000 0000 0011 0000 0011 1001 你为什么不找到一个四字节二进制可以容纳的最大值,然后数一下是多少位数?另外,我建议您将 TRUNC(BIN) 作为二进制字段的编译器选项(在编译列表的开头检查)。如果您在 ID DIVISION 标头前面添加 CBL TRUNC(STD) 并与之对齐,然后再次编译并运行,请使用结果更新您的问题(编辑问题下的链接)。 @Ashi - 比尔的答案有什么遗漏吗?如果不是,它解决了你的问题(它似乎在做什么):请接受答案。如有遗漏,请发表评论。 【参考方案1】:在IBM的Enterprise COBOL中,定义二进制字段有四种方式:COMP; COMP-4;二进制; COMP-5。
这是怎么发生的?一个 COMPUTATIONAL 字段(简称 COMP,这里是“所有 COMPUTATIONAL 字段”的缩写)是“实现者定义的”。这意味着在一个编译器中什么是 COMP-something,在另一个编译器中可能是 COMP-somethingelse,甚至可能没有直接的等价物。
是的,您可以根据需要对 COMPUTATIONAL、COMPUTATIONAL-4 和 COMPUTATIONAL-5 进行编码。编译器会很高兴的。
为了使事物标准化,1985 年的 COBOL 标准引入了 BINARY 和 PACKED-DECIMAL 作为 USAGE。对于其他 COBOL 编译器的可移植性,这些将是 COMP 和 COMP-3(压缩十进制)字段的最佳用法。
这些不同的二进制字段有什么区别?大多数情况下,没有。 COMP、COMP-4 和 BINARY 在编译器中实际上是彼此的同义词(更准确地说,COMP-4 和 BINARY 是 COMP 的同义词)。
COMP-5,也称为“本机二进制”,是不同的。 COBOL 具有您可能称之为“十进制二进制”字段(COMP 和同级)的内容。也就是说,数据以二进制形式存储,但其最大值和最小值是定义中使用的 PICture 子句的数量和完整值。
COMP PIC 9 - can contain zero to nine.
COMP PIC S99 - (signed) can contain -99 to +99.
COMP PIC 999 - can contain zero to 999.
COMP-5 不同。
COMP PIC 9 - can contain zero to 65535.
COMP PIC S99 - (signed) can contain -32768 to +32767.
COMP PIC 999 - can contain zero to 65535.
COMP-5 发生的情况是 PICture 用于定义字段的大小(与其他二进制字段一样),但每个可能的位值都是有效的。
图片与定义的大小有何关系? PIC 9 到 PIC 9(4) 将存储在一个半字大小的字段中(即两个字节)。 PIC 9(5) 到 PIC 9(9) 将存储在一个字长的字段中(即四个字节)。 PIC 9(10) 到 PIC 9(18) 将存储在一个双字大小的字段(八个字节)中。
好的,那么这种差异(COMP-5 使用所有位,COMP 只能表示 PICture 的十进制值)如何影响定义的内容? “原生二进制”听起来不是比“非原生”的任何东西都好得多,而且明显更快吗?
不同之处在于它们的截断方式。而且,就像“原生二进制”听起来一样闪烁,由于截断,它通常比使用 COMP 和 CO 慢。
COMP 截断为 PICture 的十进制值。 COMP-5 截断到字段的大小。
考虑(名称仅用于演示,仅使用描述性名称):
01 PROGA COMP PIC 9(4).
01 PROGB COMP-5 PIC 9(5).
01 PROGC BINARY PIC 9(4) VALUE 9999.
ADD PROGC TO PROGA
ADD PROGC TO PROGB
记住 PROGA 的最大值为 9999,并注意到 19998 很容易适应字段的现有大小,编译器可以实现加法,然后截断为十进制值,全部就地。
记住 PROGB 的最大值为 65535,并且在原始字段中有足够的空间来成功添加进一步的 65535,编译器必须生成一个两倍于原始大小的临时字段,执行加法,然后截回原始最大值,将结果返回到原始字段。
ADD 1 TO PROGA
ADD 1 TO PROGB
请注意,对于这两个,ADD 1 TO PROGA,因为它小于 9999,仍然允许 ADD 就地完成(显然)但是 ADD 1 TO PROGB 仍然需要字段的扩展和所有的混乱,因为 PROGB 中可能已经有 65535 的值,所以编译器必须允许这样做。
来到 DISPLAY。你有 COMP PIC S9(5),你得到一个 10 位的输出。为什么?好的,您已经计算出大小,该字段长四个字节。但是,这应该会为您提供五位数的输出,范围为 -99999 到 +99999。让我们假设您的领域是 COMP-5 PIC S9(5)。
使用 COMP-5,您的所有位都是有效的,对于带符号的字段,您的全字/字的范围是 -2,147,483,648 到 +2,147,483,647。这是 10 位数字,请注意。与您在输出中获得的 10 位数字匹配。发生了什么?
编译器选项 TRUNC。如果您使用编译器选项 TRUNC(BIN),您的所有 COMP/COMP-4/BINARY 字段都被视为 COMP-5。故事结局。您有 TRUNC(BIN) 由您、您的项目特别选择,或者作为您的站点默认值。这不一定是一个好的选择。
编译器选项 TRUNC 的其他值是 STD,它对 COMP/COMP-4/BINARY 进行“正常”截断,而 OPT 则在当时(为了性能)做任何最好的事情。
请注意,强烈不要,TRUNC(OPT) 将合同强加给程序员。 “我不会,绝对不会,甚至永远不会考虑,允许 COMP/COMP-4/BINARY 字段具有不符合其图片的值。如果我这样做,那完全是我的错,句号,故事的结尾,我没有哭泣”。
除了为了调查事情是如何运作的目的之外,不要只启动并更改 TRUNC 设置。如果你这样做了,你可以打破一些东西,这可能是一个非常非常微妙的突破。
我的建议:TRUNC(BIN),除非万不得已,否则不要使用它(有人决定了,你别无选择);如果您的网站害怕合同,请使用 TRUNC(STD);如果您的网站对合同感到满意,请使用 TRUNC(OPT)。
请在需要的地方使用 COMP-5 来进行单独的字段定义。你需要去哪里?对于任何地方,您都有一个二进制字段,其范围超出其图片的“十进制值”。例如,查看 CICS COMMAREA 的大小和指示单个示例有多大的字段。查看 COBOL 程序中的 VARCHAR 主机字段。与 JAVA 或 C/C++ 通信的数据可能是这样的。否则,对于新程序,请选择 BINARY,这表明您与 1985 年保持同步。
为调查目的设置 TRUNC。
CBL TRUNC(STD)
ID (or IDENTIFICATION) DIVISION.
编译器选项也可以由 JCL 中的 PARM 语句设置以进行编译,但您可能无权访问它。 CBL 将覆盖 PARM 中设置的任何值。有一个安装选项可以阻止使用 CBL(也称为 PROCESS)。个别选项也可以在安装时“固定”。如果您的网站修复了 TRUNC 或阻止了 CBL,您将无法尝试这些事情。
【讨论】:
【参考方案2】:COMP
使用子句将被称为BINARY
或COMPUTATION
。
COMP
用法子句仅适用于数值数据类型。
COMP
用法是数据的二进制表示。
COMP
变量中的数据以纯二进制格式存储在内存中。
COMP
USAGE 的内存分配如下。
Picture Number of Bytes
S9 to S9(4) 2
S9(5) to S9(9) 4
S9(9) to S9(18) 8
【讨论】:
以上是关于在 COBOL 中使用 COMP 的变量的主要内容,如果未能解决你的问题,请参考以下文章
如何在 COBOL 的链接部分中使用外部变量并将值从它传递到新模块并写入我的新输出文件
如何用COBOL语言生成随机数?如何截取字符串?知道的大哥大姐告诉一下,谢谢O(∩_∩)O~