2016-09-21 34 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)