2016-09-21 4 views
1

제공합니다.AS400 CL 스크립트 산술 내가 알고리즘 부문의 나머지를 계산하기 위해 노력하고있어 0

예 : 15/6

1. (15/6) = 2 
2. (2) * 6 = 12 
3. 15 - 12 = 3 
의 나머지 6분의 15의 나머지 부분은 참으로

받기 3.

는 내 CL 스크립트에서이 알고리즘을 사용하고 내 문제는 단순히 모든 0을 반환

시간. 왜 그런가요?

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

실행 :

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 

함께 컴파일

call test 

출력 :

0 
+0

이 날짜 24 9 월 2016로, 영업에 표시된 CL 프로그램 소스 코드는 반드시을 전시 무엇을 복사 \ 붙여 넣기 아니다 기술 된 어려움; 즉 첫 번째'CHGVAR'의 표현은 분명히 "계산하려고"한 표현과 일치하지 않습니다. 결과는 항상 주제 피험자가 기술 한 0이 아닌'& dividend'의 초기 값입니다. 표제. – CRPence

+0

해당 표현식의 값이 나눗셈의 자르기에서 다른 정수 유형이어야하기 때문에 아니요. 최소한 그것은 괜찮은 프로그래밍 언어에서 일어날 일입니다. –

+1

"아니오"는 무엇입니까? 나는 '나머지 = 배당 - (배당/제수) * 제수'는 '나머지 = 배당 - (배당/제수) * 나머지'와 같은 표현이 아니라는 점을 지적했다. CL 소스는 후자를 코딩했다. 정수 나누기, 모든 알맞은 프로그래밍 언어는 정수 나누기 연산자와 어리석게도 두 개의 정수 피연산자가있는 정수 만 결과를 내 보내지 않는 다른 나누기 연산자를 제공합니다. CL은 어리석게도 정수 결과를 강제하지 않지만 정수 나누기 연산자를 제공하지 못합니다. 그러나 CL은 강력한 * 제어 언어로서 실제 프로그래밍 언어가 아닙니다. – CRPence

답변

1

이것은 매우 흥미로운 시스템 동작입니다. 엔진은 곱하기 전에 대괄호 안의 값에 정수 트렁킹을 적용하지 않는 것으로 보입니다. 환언에서 일어나는 다음

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

가 I 한 다음 그것을 해결하기 :

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 인 char 변수에서 결과를 얻는 방법을 고치는 방법을 알고 있습니까? –

+0

변수를 추가하십시오 : dcl var (& msgd) type (* dec) len (1). 그런 다음 chgvar var (& msgd) 값 (& 나머지) 및 chgvar var (& msg) 값 (& msgd). 그러면 문제가 해결 될 것입니다. 귀하의 질문에 답한 경우 내 대답을 수락하는 것을 잊지 마십시오. –

+0

7.2에서 CL은 % DEC 및 % INT와 같은 몇 가지 기본 제공 함수를 추가로 작성했습니다. –

1

설명 된 결과를 상기 분할 연산자로 부호화 된 /의 부작용. / 연산자는 정수 부 연산자가 아닙니다. 일부 언어는 //을 해당 효과의 추가 나누기 연산자로 제공하거나 DIV과 같은 스칼라 함수로 제공 할 수 있습니다. 그러나 언어가 그러한 추가 산술 기능을 제공하는 경우에는 MOD 또는 REM과 같은 관련 스칼라를 제공하여 나머지를 직접 얻을 수도 있습니다.

IRP 목록은 명시 적으로 코드화 된 것처럼 작동하는 CL이 0이 아닌 스케일을 갖는 중간 값을 갖는 것으로 나타났습니다. 효과적으로 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/&divisor) [표현식 &dividend - (&dividend/&divisor) * &divisor의 일부로] 정수 결과를 산출해야하기 때문에 해당 나누기 연산의 중간 결과가 * INT 유형 또는 제로 스케일이있는 다른 숫자 유형으로 강제 지정되어야 함을 의미합니다.
그리고 이미 허용 대답 쇼로, 다음과 같은 개정은 중간 결과에 대한 정수를 사용하는 문제 해결 : 나는 OP에 24Sep 주석에 언급 무엇 달리

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 ) 

은 더 능력이 없다 단 하나의 CHGVAR 문에서 원하는 결과를 얻으려면 다음 표현식을 코딩하십시오. 첫 번째 표현식은 msg를 사용한 구문 검사에 실패합니다. CPD0058 "내장 함수 % INT는 1 개의 인수를 허용합니다." 두 x 째는 msg CPD0181 "내장 함수 % INT의 인수가 유효하지 않습니다."와 함 2 실패합니다. 그리고 나는 같은 효과를 기대할 것이다. (그러나 나는 확인하지 않았다.) % DEC 내장 함수를 코딩하지 않았다. 즉 제로는 진수 - 장소 인수]에 지정된 :

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

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