2016-09-21 41 views
1

を与えます。AS400 CLスクリプト演算は、私はアルゴリズムで割り算の余りを計算しようとしている0

例: 私の問題は、単に0を返すすべての私のCLスクリプトでこのアルゴリズムを使用している

6分の15の残りの部分は確かに3

で15/6

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

の残りの部分を取得します。時間。何故ですか?

でコンパイル
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に示したCLプログラムのソースコードを、この日付24 9月 - 2016年のように、確実に発揮するもののコピー\ペーストではありません説明したような困難。すなわち、最初の 'CHGVAR'の式は、明らかに「計算しようとしています」という表現に一致していません。その結果は、トピックsubjectで記述されているゼロではなく、常に'&dividend'の初期値になります。タイトル。 – CRPence

+0

上記の式の値が整数の型であり、除算の切り捨てが異なる必要があるためです。少なくとも、それはまともなプログラミング言語で起こるはずのことです。 –

+1

「いいえ」は何ですか? 「残余=配当 - (配当/除数)*除数」は、「残余=配当 - (配当/除数)*残余」と同じ表現ではないことを指摘した。 CLソースは後者をコード化した。 整数の除算では、まともなプログラミング言語は、整数除算演算子と、2つの整数オペランドを持つ整数のみの結果を愚かに強制しない別の除算演算子の両方を提供します。 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

ありがとうございます。私は2番目の問題があります。 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)の値(&remainder)とchgvar var(&msg)の値(&msgd)を入力します。それはあなたの問題を解決するはずです。あなたの質問に答えたら私の答えを受け入れることを忘れないでください。 –

+0

7.2では、CLは%DECや%INTなどの組み込み関数をいくつか追加しています。 –

1

記載の結果は、除算演算子として符号化された/の副作用です。 /演算子は、整数除算演算子ではありません。いくつかの言語は、//をその効果のための追加の除算演算子として、または恐らくDIVのようなスカラー関数として提供することができる。しかし、言語がそのような追加の算術機能を提供するときには、MODまたはREMのような関連するスカラーを提供して、残りを直接取得する可能性があります。

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/&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 ) 

何の能力がない:
そして、既に受け入れ答えが示すように、中間結果のために整数を使用するには、次のリビジョンが問題を解決します次の式
をコーディングして、1つのCHGVARステートメントで目的の結果を達成します。最初の式はmsgの構文チェックに失敗します。CPD0058 "組み込み関数%INTは1つの引数を許可します。" 2番目はmsg CPD0181 "組み込み関数%INTの引数が無効です"で失敗します。そして、私は同じ効果が期待されますが、%DEC組み込み関数をコーディングすることから検証しませんでした。すなわちゼロ小数点-場所を引数]指定:

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

(&dividend - %int((&dividend/&divisor)) * &divisor) 
関連する問題