1

アルゴリズムで除算の剰余を計算しようとしています:

remainder = dividend - (dividend / divisor) * divisor

すべて整数で計算されます。

例: 15 / 6 の余りを取得します。

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

15/6 の余りは確かに 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
4

2 に答える 2

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)  
于 2016-09-22T05:53:55.587 に答える
1

/記述された結果は、除算演算子としてコーディングされた の副作用です。この/演算子は、CLの整数除算演算子ではありません。一部の言語は//、その効果の追加の除算演算子として、またはおそらく a などのスカラー関数として を提供する場合がありDIVます。ただし、言語がそのような追加の算術機能を提供する場合、剰余などの関連するスカラーも提供するMODREM、剰余を直接取得する可能性があります。

IRP のリストから、CL がゼロ以外のスケールの中間値を持つように明示的にコード化されているかのように動作することが明らかになりました。しかし、 CLTYPE(*DEC) LEN(24 9)では 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 型またはゼロスケールの別の数値型にする必要があります。
そして、すでに受け入れられている回答が示すように、中間結果に整数を使用する次のリビジョンは問題を解決します:

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 コメントで言及したこととは異なり、次の式をコーディングして、 1 つの CHGVAR ステートメントだけで目的の結果を達成することはできません。最初の式は、メッセージ CPD0058 "組み込み関数 %INT は 1 つの引数を許可します" で構文チェックに失敗します。2 つ目は、メッセージ CPD0181「組み込み関数 %INT の引数が無効です。」で失敗します。そして、%DEC ビルトインを [0 スケールを指定して] コーディングしても [ただし確認はしていません]、同じ効果が期待できます。つまり、引数decimal-placesにゼロを指定]:

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

( &dividend - %int((&dividend / &divisor)) * &divisor )
于 2016-09-29T16:56:15.073 に答える