在AS / 400中使用COMPUTE函数时,我遇到了一个神秘的问题。
场景如下:
01 WSAA-AMOUNT-A PIC S9(15)V9(02) COMP-3.
01 WSAA-AMOUNT-B-01 PIC S9(16)V9(02) VALUE 0.
01 WSAA-AMOUNT-B-02 PIC S9(13)V9(05) VALUE 0.
01 WSAA-AMOUNT-C PIC S9(16)V9(02) VALUE 0.
01 WSAA-RESULT PIC S9(15)V9(02) VALUE 0.
MOVE 2500.87 TO WSAA-AMOUNT-A.
MOVE 12285 TO WSAA-AMOUNT-B-01.
MOVE 12285 TO WSAA-AMOUNT-B-02.
MOVE 4387.5 TO WSAA-AMOUNT-C.
COMPUTE WSAA-RESULT ROUNDED = (WSAA-AMOUNT-A / ( WSAA-AMOUNT-B-01 + WSAA-AMOUNT-C) * 100 ).
DISPLAY WSAA-RESULT.
COMPUTE WSAA-RESULT ROUNDED = (WSAA-AMOUNT-A / ( WSAA-AMOUNT-B-02 + WSAA-AMOUNT-C) * 100 ).
DISPLAY WSAA-RESULT.
结果使我感到惊讶,第一个公式的结果= 14.90
而第二个变成= 15
听起来后一个更合乎逻辑,例如2500.87 /(12285 + 4387.5)* 100 = 14.99997001。
我希望四舍五入后的第一个结果也应为15。
有谁知道结果不一致的根本原因是什么?
最佳答案
达到的结果是14.90和15.00。
COMPUTE的格式不正确。乘以100时,请尽早执行,因为如果您最后进行一次,则两个小数位会消失(除以100时,最后要保留小数位,这样就不会早早丢失有效数字)。
它不仅适用于100,所以请考虑一下。无论涉及什么值,都先乘以,最后除。除非您在最终答案中要求五个小数位,否则完全没有必要使用具有五个小数位的字段来获得“正确”答案。
该计算机不是计算器或电子表格。它使用中间结果取决于您的要求,而不是根据其他结果而为您提供许多小数位。您使用所使用的字段中的小数位数要求十进制精度。
精细手册是了解正在发生的事情的一个关键。另一个是实验。这通常是一个普遍的答案。
COMPUTE WSAA-RESULT ROUNDED =
(WSAA-AMOUNT-A / ( WSAA-AMOUNT-B-01 + WSAA-AMOUNT-C) * 100 )
显示WSAA结果。得到答案14.90(十四点九零)。
COMPUTE WSAA-RESULT =
(WSAA-AMOUNT-A / ( WSAA-AMOUNT-B-01 + WSAA-AMOUNT-C) * 100 )
显示WSAA结果。通过删除ROUNDED,得到答案14.00(十四点零-零)。
COMPUTE WSAA-RESULT ROUNDED =
(WSAA-AMOUNT-A / ( WSAA-AMOUNT-B-02 + WSAA-AMOUNT-C) * 100 )
通过使用五个小数位,DISPLAY WSAA-RESULT得到15.00(零点零零)为“正确”“预期”答案。
请记住,您最后乘以100。因此在此之前,值分别为0.149(小数点后三位),0.14(小数点后两位)和14.99999n(小数点后六位),我不再进行计算,因此我将第六个留为“ n”)。
为什么小数点后三,二和六?六个是因为B-02(具有五个位,再加上一个用于ROUNDED,则将所需的小数位增加1,以便可以计算ROUNDED),两个是由于B-01(具有两个小数位) )这三个是因为B-01和ROUNDED。
这是三个版本中的重新设计的COMPUTE:
COMPUTE WSAA-RESULT ROUNDED = ( ( WSAA-AMOUNT-A * 100 )
/ ( WSAA-AMOUNT-B-01
+ WSAA-AMOUNT-C ) )
COMPUTE WSAA-RESULT = ( ( WSAA-AMOUNT-A * 100 )
/ ( WSAA-AMOUNT-B-01
+ WSAA-AMOUNT-C) )
COMPUTE WSAA-RESULT ROUNDED = ( ( WSAA-AMOUNT-A * 100 )
/ ( WSAA-AMOUNT-B-02
+ WSAA-AMOUNT-C) )
结果是15.00、14.99和15.00。
这是Enterprise Cobol。似乎OpenCobol使用了不同的中间结果,这些中间结果可能已记录在案。
这是有关中间结果的《企业Cobol编程指南》:
“要了解有关中间结果的信息,您需要了解以下术语。
...
d中间结果的小数位数。 (如果使用ROUNDED短语,则如有必要,可能还会再保留小数点后一位。)
dmax在特定的语句中,以下最大的一项:
v最终结果字段或多个字段所需的小数位数
v为任何操作数定义的最大小数位数,
除数或指数除外
v任何函数操作数的外部dmax”
和
"Operation ... Decimal places
+ or - ... d1 or d2, whichever is greater
* ... d1 + d2
/ ... (d2 - d1) or dmax, whichever is greater"
在“错误”示例中,加法运算得到两个小数位(d1和d2均为两个小数),除法运算得到三个小数位(dmax为3),乘法运算得到三个(ROUNDED为2 + 0 + 1) )。尝试四舍五入后的最终答案(由于两个低位小数由于乘以100而始终为零,因此它将永远不会起作用)被截断为两位小数。
对于ROUNDED B-01,dmax为3(两个字段的结果字段加一个四舍五入)。对于普通的B-01,dmax为2。对于ROUNDED B-02,dmax为6。
请注意,错误的不仅是显示的示例。在问题的第一个示例中,ROUNDED从不进行操作,并且始终删除一个有效的小数,因此,只有在四舍五入前的答案为十分之一时,您才获得正确的答案。然后,这些正确答案被九个另外的答案掩盖,这些其他答案由于截断而变得相同。
如果您始终编写有效的COMPUTE,就不会遇到问题。 ROUNDED仅对最终结果起作用。如果您需要任何中间字段,请分别计算并在新的计算中使用该结果。
计算工作。 COMPUTE不能像计算器/电子表格那样运行。任何其他Cobol动词(它们都是动词而不是函数)也没有。考虑如何编写COMPUTE,以免失去意义。阅读手册。实验。重复直到正确并理解为止。
关于ibm-midrange - AS/400:使用COMPUTE函数时,不同字段定义的结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14272981/