Using IBM i? Need to create Excel, CSV, HTML, JSON, PDF, SPOOL reports? Learn more about the fastest and least expensive tool for the job: SQL iQuery.
Good morning. A coworker is trying to put a 9.0 field into an 8.0 field in freeform and he gets the error about the receiving field not being large enough. He said that he doesn't care what's in the 9th position.
I suggested that maybe he could cast the 9.0 field somehow, to an 8.0 value in the move. Maybe something like this:
field80 = %dec(field90:8:0);
Is anything like this valid?
You only get the error when the value won't fit, if the value is 099999999, then eval will work.
Lose the last digit: Field80 = %div(Field90:10)
Lose the first digit: Field80 = %rem(Field90:100000000)
That compiler message is a warning, not an error. It's perfectly valid to use one of these:
Field80 = Field90;
Field80 = %DEC(Field90:8:0);
They are more or less equivalent. The first tries to move a 9P0 into an 8P0, aligned on the decimal point. The second explicitly converts 9P0 to 8P0 aligned on the decimal point, then moves the result of that to 8P0. Either way, there's no runtime error if the value of Field90 fits in the 8P0. If you care about the overflow, you'd probably put it in a Monitor group, or do an If/Else.
You said you don't care, so you just want it to truncate the high order digit, like a fixed format Z-ADD, I'd probably use the %REM(Field90:100000000) as suggested by Neil.
There are other methods that might be cheaper than %REM. Without actually benchmarking it, I'll postulate that using a DS with overlay could be faster:
DField90 S 9P 0
DField80 S 8P 0
D DS
D Wrk9S0 9S 0
D Wrk8S0 8S 0 OVERLAY(Wrk9S0:2)
/FREE
Wrk9S0 = Field90; // convert packed to zoned
Field80 = Wrk8S0; // convert zoned to packed
/END-FREE
%REM does a division to get the remainder. Converting packed to zoned, and zoned to packed only involves moving nybbles around, with no actual calculations.
At the end of the day "truncation" is different from trapping an error.
You can only use MOVE, Z-ADD to avoid the error when there is high-order truncation. Otherwise a MONITOR group can be used to trap the error, however you WILL loose all the digits, not just the high-order 1.
I do have a work around that I've published. Don't recall if it is here on MidrangeNews.com or in a previous life. I'll look around for it and either post it here, or post the link to it.
Come to think of it, even the truncation that happens with MOVE and Z-ADD is actually done by internally trapping the exception. Seem to remember reading several years ago that the internal exception processing imposes a performance penalty.
But you don't lose anything. If you put the straight Eval in a Monitor, either the straight Eval works or it doesn't. If you fall into the On-Error, you run the workaround code and "convert" Field90 in a different way.
The routine is TRUNCDEC
P truncDec b export D truncDec pi 63p31 D val 63p31 const D digits 10i 0 value D decposParm 10i 0 value options(*nopass) D decpos s 10i 0 inz(0) D valString s 70a D newString s 70a D sign s 1a inz('+') D startPos s 10i 0 inz(0) /free if %parms >= 3; decpos = decposParm; endif; if val < 0; sign = '-'; endif; valString = %editc(%abs(val) : 'P'); valString = %xlate(' ':'0':valString); startPos = %scan('.' : valString) - (digits - decpos); newString = sign + %subst(valString : startPos : digits + 1); return %dec(newString : 63 : 31); /end-free P truncDec e
You call it with the original value and the target length and optional decimal positions and it copies the source to the target truncating any digits higher than the length specified on parameter 1. You can pass %LEN(target) and %DECPOS(target) if you like.