as400 CL脚本算术给出0
as400 CL script arithmetic gives 0
我正在尝试使用以下算法计算除法的余数:
remainder = dividend - (dividend / divisor) * divisor
全部以整数计算。
示例:
得到 15 / 6 的余数。
1. (15 / 6) = 2
2. (2) * 6 = 12
3. 15 - 12 = 3
15/6的余数确实是3
我的问题是在我的 CL 脚本中一直使用这个算法 returns 0。这是为什么?
pgm
dcl var(÷nd) 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(÷nd - (÷nd / &divisor) * &divisor)
/* Prior to 29-Sep-2016 redaction, the above was coded as the incorrect expression: +
chgvar var(&remainder) value(÷nd - (÷nd / &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
这是一个非常有趣的系统行为。看起来引擎在乘以它之前不会将整数中继应用于括号中的值。所以换句话说,发生了以下情况:
÷nd - (÷nd / &divisor) * &divisor
= 15 - (15 / 6) * 6
= 15 - 2.5 * 6
= 15 - 15
= 0
为了修复它,我做了以下操作:
chgvar var(&remainder) value(÷nd / &divisor)
chgvar var(&remainder) value(÷nd - &remainder * &divisor)
所描述的结果是编码为除法运算符的 /
的副作用。 /
运算符不是 CL 中的 整数除法 运算符;某些语言可能会提供 //
作为该效果的附加除法运算符,或者可能作为标量函数,例如 DIV
;尽管当一种语言提供此类额外的算术功能时,它们也可能会提供相关的标量,例如 MOD
或 REM
以直接获得余数。
IRP 列表显示 CL 的运行就像明确编码为具有非零标度的中间值;实际上 TYPE(*DEC) LEN(24 9)
,但 CL 只允许 15 位精度,所以我在这个程序示例中使用 TYPE(*DEC) LEN(15 5)
,该程序模拟在执行表达式的其余部分之前创建除法的中间结果:
pgm
dcl var(÷nd) 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(÷nd / &divisor) /* P15,5 intermed result */
chgvar var(&remainder) value(÷nd - &intermedP * &divisor )
因为正确的结果要求 (÷nd / &divisor)
[作为表达式 ÷nd - (÷nd / &divisor) * &divisor
] 的一部分必须产生整数结果,这意味着该除法运算的中间结果必须强制为 *INT 类型或另一种具有零刻度的数字类型。
并且如已接受的答案所示,对中间结果使用整数的以下修订解决了该问题:
pgm
dcl var(÷nd) 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(÷nd / &divisor) /* *INT intermed result */
chgvar var(&remainder) value(÷nd - &intermedI * &divisor )
与我在 9 月 24 日对 OP 的评论中提到的不同,无法编写以下表达式 以仅在一个 CHGVAR 语句中获得所需的结果;第一个表达式未通过 msg CPD0058 "Built-in function %INT allows 1 arguments." 语法检查,第二个表达式未通过 msg CPD0181 "Argument for built-in function %INT not valid."。而且我希望通过编码内置的 %DEC [具有零刻度规范;但我没有验证]同样的效果;即为 小数位 参数指定的零]:
( ÷nd - %int(÷nd / &divisor) * &divisor )
( ÷nd - %int((÷nd / &divisor)) * &divisor )
我正在尝试使用以下算法计算除法的余数:
remainder = dividend - (dividend / divisor) * divisor
全部以整数计算。
示例: 得到 15 / 6 的余数。
1. (15 / 6) = 2
2. (2) * 6 = 12
3. 15 - 12 = 3
15/6的余数确实是3
我的问题是在我的 CL 脚本中一直使用这个算法 returns 0。这是为什么?
pgm
dcl var(÷nd) 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(÷nd - (÷nd / &divisor) * &divisor)
/* Prior to 29-Sep-2016 redaction, the above was coded as the incorrect expression: +
chgvar var(&remainder) value(÷nd - (÷nd / &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
这是一个非常有趣的系统行为。看起来引擎在乘以它之前不会将整数中继应用于括号中的值。所以换句话说,发生了以下情况:
÷nd - (÷nd / &divisor) * &divisor
= 15 - (15 / 6) * 6
= 15 - 2.5 * 6
= 15 - 15
= 0
为了修复它,我做了以下操作:
chgvar var(&remainder) value(÷nd / &divisor)
chgvar var(&remainder) value(÷nd - &remainder * &divisor)
所描述的结果是编码为除法运算符的 /
的副作用。 /
运算符不是 CL 中的 整数除法 运算符;某些语言可能会提供 //
作为该效果的附加除法运算符,或者可能作为标量函数,例如 DIV
;尽管当一种语言提供此类额外的算术功能时,它们也可能会提供相关的标量,例如 MOD
或 REM
以直接获得余数。
IRP 列表显示 CL 的运行就像明确编码为具有非零标度的中间值;实际上 TYPE(*DEC) LEN(24 9)
,但 CL 只允许 15 位精度,所以我在这个程序示例中使用 TYPE(*DEC) LEN(15 5)
,该程序模拟在执行表达式的其余部分之前创建除法的中间结果:
pgm
dcl var(÷nd) 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(÷nd / &divisor) /* P15,5 intermed result */
chgvar var(&remainder) value(÷nd - &intermedP * &divisor )
因为正确的结果要求 (÷nd / &divisor)
[作为表达式 ÷nd - (÷nd / &divisor) * &divisor
] 的一部分必须产生整数结果,这意味着该除法运算的中间结果必须强制为 *INT 类型或另一种具有零刻度的数字类型。
并且如已接受的答案所示,对中间结果使用整数的以下修订解决了该问题:
pgm
dcl var(÷nd) 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(÷nd / &divisor) /* *INT intermed result */
chgvar var(&remainder) value(÷nd - &intermedI * &divisor )
与我在 9 月 24 日对 OP 的评论中提到的不同,无法编写以下表达式 以仅在一个 CHGVAR 语句中获得所需的结果;第一个表达式未通过 msg CPD0058 "Built-in function %INT allows 1 arguments." 语法检查,第二个表达式未通过 msg CPD0181 "Argument for built-in function %INT not valid."。而且我希望通过编码内置的 %DEC [具有零刻度规范;但我没有验证]同样的效果;即为 小数位 参数指定的零]:
( ÷nd - %int(÷nd / &divisor) * &divisor )
( ÷nd - %int((÷nd / &divisor)) * &divisor )