2016-09-21 81 views
1

我试图计算除法的算法,其余:AS400 CL脚本算术给出0

remainder = dividend - (dividend/divisor) * divisor 

的整数计算所有。

举例: 获得的15/6

1. (15/6) = 2 
2. (2) * 6 = 12 
3. 15 - 12 = 3 

的6月15日的剩余确实3.

我的问题在我的CL脚本使用这种算法只是返回0所有时间。这是为什么?

pgm 
dcl var(&dividend) type(*int) value(15) 
dcl var(&divisor) type(*int) value(6) 
dcl var(&remainder) type(*int) 

dcl var(&msg) type(*char) 

/* Calculate remainder. [ed: 29Sep2016] "* &remainder" is now: "* &divisor" */ 
chgvar var(&remainder) value(&dividend - (&dividend/&divisor) * &divisor) 

/* Prior to 29-Sep-2016 redaction, the above was coded as the incorrect expression: + 
chgvar var(&remainder) value(&dividend - (&dividend/&divisor) * &remainder)  + 
    and remains, commented-out, to preserve relevance of user-comments about the OP */ 

/* Cast remainder and display. */ 
chgvar var(&msg) value(&remainder) 
sndpgmmsg msg(&msg) 

endpgm 

编译时:

crtclpgm pgm(test) srcfile(test) srcmbr(test) 

运行:

call test 

输出:

0 
+0

在OP显示,截至今天24月 - 2016 CL程序的源代码,是肯定不会的东西表现出的副本\粘贴描述的困难;即第一个“CHGVAR”表达式的表达式与“试图计算”的表达式明显不符 - 并且结果将始终是“&dividend”的初始值,而不是主题subject \标题。 – CRPence

+0

否,因为所述表达式中的值是类型整数,其在分割的截断中应该不同。至少在任何体面的编程语言中都会发生这种情况。 –

+1

“不”是什么?我指出“剩余=股息 - (股息/除数)*除数”与“余额=股息 - (股息/除数)*余数”不同。 CL来源编码后者。 Re整数除法,任何不错的编程语言都提供了整数除法运算符和另一个除法运算符,它不会愚蠢地强制使用两个整数运算数的整数结果。 CL并不愚蠢地强制整数结果,但未能提供整数除法运算符 - 但CL是一种强大的控制语言,并不意味着它是一种真正的*编程语言。 – CRPence

回答

1

这是很有趣的系统行为。似乎该引擎在将其与括号中的值相乘之前不会对其应用整数中继。因此,换句话说,正在发生以下:

&dividend - (&dividend/&divisor) * &divisor 
= 15 - (15/6) * 6 
= 15 - 2.5 * 6 
= 15 - 15 
= 0 

要解决它,我做了以下内容:

chgvar  var(&remainder) value(&dividend/&divisor) 
chgvar  var(&remainder) value(&dividend - &remainder * &divisor) 
+0

谢谢。我有第二个问题。由于除以10的余数总是1位长,因此我将& msg变量的长度更改为1:dcl var(&msg)type(* char)len(1)。但是当我这样做时,它似乎根据股息价值崩溃,它给我错误CPF0819,它代表变量太短而无法保持结果。你知道如何解决这个或另一种方式来获得长度为1的字符变量的结果吗? –

+0

添加变量:dcl var(&msgd)type(* dec)len(1)。然后chgvar var(&msgd)值(&余数)和chgvar var(&msg)值(&msgd)。这应该解决你的问题。如果回答你的问题,请记住接受我的回答。 –

+0

请注意,在7.2中,CL增加了一些额外的内置函数,例如%DEC和%INT。 –

1

所描述的结果是,被编码为除法运算符的/的副作用。在CL中,/运算符不是整数除法运算符;某些语言可能会提供//作为此效果的附加划分运算符,或者可能将其作为标量函数,如DIV;尽管当语言提供这样的附加算术特征时,它们也可能提供相关的标量,例如MODREM以直接获得余数。

IRP列表揭示了CL的操作,就好像显式编码为具有非零值的中间值;有效TYPE(*DEC) LEN(24 9),但CL仅允许15位精度,所以在模仿中间结果的创建为师执行表达式的其余部分之前的程序的本实施例中使用TYPE(*DEC) LEN(15 5)

pgm 
dcl var(&dividend) type(*int) value(15) 
dcl var(&divisor) type(*int) value(6) 
dcl var(&remainder) type(*int) 
dcl var(&intermedP) type(*dec) len(15 5) 
/* Calculate remainder. *two-step process -- mimics IRP listing; yields 0 */ 
chgvar var(&intermedP) value(&dividend/&divisor) /* P15,5 intermed result */ 
chgvar var(&remainder) value(&dividend - &intermedP    * &divisor ) 


由于正确的结果要求[作为表达式&dividend - (&dividend/&divisor) * &divisor]的一部分的(&dividend/&divisor)必须产生整数结果,这意味着该除法操作的中间结果必须强制为* INT类型或具有零尺度的另一个数字类型。
并为已接受的答案显示,如下版本使用的中间结果的整数解决问题:

pgm 
dcl var(&dividend) type(*int) value(15) 
dcl var(&divisor) type(*int) value(6) 
dcl var(&remainder) type(*int) 
dcl var(&intermedI) type(*int) 
/* Calculate remainder. *two-step process; per change, correctly yields 3 */ 
chgvar var(&intermedI) value(&dividend/&divisor) /* *INT intermed result */ 
chgvar var(&remainder) value(&dividend - &intermedI    * &divisor ) 

不像我到OP一个24Sep评论提到,没有能力编码以下表达式以在仅一个CHGVAR语句中实现所需结果;第一个表达式无法通过msg检查语法CPD0058“内置函数%INT允许1个参数”。第二个失败,并带msg CPD0181“内建函数%INT的参数无效”。我期待同样的效果[但我没有验证]编码%DEC内建[与规模的零规模;即零指定为小数位参数]:

(&dividend - %int(&dividend/&divisor) * &divisor) 

(&dividend - %int((&dividend/&divisor)) * &divisor)