COBOL - 对于相同的 COMPUTE,从大型机到 PC 的不同答案
Posted
技术标签:
【中文标题】COBOL - 对于相同的 COMPUTE,从大型机到 PC 的不同答案【英文标题】:COBOL - Differing answer from mainframe to PC for same COMPUTE 【发布时间】:2016-10-04 14:04:24 【问题描述】:我有一个非常简单的虚拟 COBOL 程序,它执行虚拟 COMPUTE 并显示结果。
ID DIVISION.
PROGRAM-ID. DUMMYPGM.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 NUM-A PIC 9(3) VALUE 399.
01 NUM-B PIC 9(3) VALUE 211.
01 NUM-C PIC 9(3).
*
PROCEDURE DIVISION.
MAIN.
COMPUTE NUM-C = ((NUM-A / 100) - (NUM-B / 100)) * 100
DISPLAY 'NUM-C IS ' NUM-C
STOP RUN.
当我在大型机上编译这段代码(使用编译器 MVS Enterprise COBOL V4.2)并执行它时,我得到“NUM-C IS 100”,可能是因为 (399 / 100) 被视为 3 而不是计算中为 3.99(211 / 100 也是如此)。
但是当我在 PC 上(使用 GnuCobol 编译器)编译相同的代码并执行它时,我得到“NUM-C IS 188”。 PC的答案是正确的,但我想让它像大型机一样运行(因此,在计算语句中失去精度以给出100而不是188)......我该怎么做?
上面的原因是这段代码的一般表达:
COMPUTE PDISCR = (((((X(1) + DX - XBRAK) * (ABRAK(1) / 1000)) / 100)
+ PHT(1) + DPH - PHBRAK) * 2) + ((V(1) + DV
+ VBRAKMPM) * (V(1) + DV - VBRAKMPM) / 100000))
这是一个已有 50 年历史的火车模拟程序的一部分,我需要将其迁移到 GnuCOBOL。 COMPUTE 中使用的所有字段都是整数。我需要能够从 GnuCOBOL 获得相同的答案。
已确认 OpenCOBOL/GnuCOBOL 最高 2.0。
【问题讨论】:
对不起,误解:复杂,我的意思是单个计算中的多个操作(这里,有 2 个除法和一个乘法,而不是一个操作)。我承认代码不是很好,但这只是一个概念证明。我确实想要听起来更优秀或任何东西,所以我编辑了我的帖子。 至于 GnuCOBOL 版本,我写了 cobc -V 并得到了这个:cobc (OpenCOBOL) 1.1.0 版权所有 (C) 2001-2009 Keisuke Nishida / Roger While Built 2010 年 9 月 10 日 10:12: 33 打包 2009 年 2 月 6 日 10:30:55 CET 我知道一个可能的解决方案是将计算的每一步隔离在不同的整数变量中,但我想找到一个更好的解决方案,因为这是我的代码中的 COMPUTE 语句示例工作:计算 PDISCR = (((((X(1) + DX - XBRAK) * (ABRAK(1) / 1000)) / 100) + PHT(1) + DPH - PHBRAK) * 2) + ((V (1) + DV + VBRAKMPM) * (V(1) + DV - VBRAKMPM) / 100000))cobc -std=ibm
将在未来的版本中执行此“正确错误”,并将针对此可能的转换问题添加警告选项,请参阅sourceforge.net/p/open-cobol/feature-requests/175
哦!我没想到来自 GNUCobol 的开发人员真的会为此做点什么……我很惊讶!当然,与此同时,我已经对我的计算进行了去皮,但是如果其他人将旧的大型机代码转移到 PC 上并期望得到相同的结果,这个功能会很好。
【参考方案1】:
https://lwn.net/Articles/733129/
此链接提到了 gnuCobol 2.2 的新标准选项:ibm-strict。我想知道这是否会强制计算语句执行您想要的操作。
【讨论】:
【参考方案2】:由于看起来 IBM 会截断您的值而 GnuCobol 不会,因此您可能希望使用 GnuCobol 函数来模拟 IBM 的做法。
至少对于正整数,这可能很简单:
COMPUTE NUM-C = ((INTEGER(NUM-A / 100)) - (INTEGER(NUM-B / 100))) * 100
我没有测试这是否适用于负整数,因为 (1) doco 似乎表明它向负无穷大而不是零舍入; (2) 似乎没有TRUNCATE
函数; (3) 我假设你不在乎,因为你的数据类型无论如何都没有签名。
如果您确实需要处理负数,有数学方法可以为您解决,我建议您在不同的问题中提出。
【讨论】:
以上是关于COBOL - 对于相同的 COMPUTE,从大型机到 PC 的不同答案的主要内容,如果未能解决你的问题,请参考以下文章