Currently, %DEC and %DECH don't support non-constant precision and scale parms. If that is to remain as is, then it would be *very* helpful if at least %CHAR(numeric) would not only support precision and scale parms, but would also support them as non-constant data.
The reason for this is because %CHAR is often used in conversion to character situations where the input to the process is the result of a calculation--and where the number of resulting decimal positions vary. It would be helpful if such calculation did not have to use intermediate variable storage before finally being fed into %CHAR. But, even then, intermediate variable storage is not that helpful in situations where you're trying to use a generic routine that will support a variable number of decimal places.
Use Case: For example... Given the following situation, the first problem is that the decimal point is lost completely. (Note that rather than initialized, use_scale would be the result of a parameter coming into the procedure.)
dcl-s packed_data packed(46:0);
dcl-s use_scale packed(2:0) inz(2);
dcl-s d_shift packed(17:0);
d_shift = %int(10 ** use_scale);
return %char(packed_data/d_shift);
So, then we add the following to the process.
ctl-opt decprec(63);
Now when the above runs you get the decimal point but you also get way too many zero decimal positions. Logically, one might then be tempted to do the following.
return %char(%dech(packed_data/d_shift:%len(packed_data):use_scale));
However, that is not supported. So, what I ended up doing is the following.
select;
when use_scale = 15;
return %char(%dech(packed_data/d_shift:46:15));
when use_scale = 14;
return %char(%dech(packed_data/d_shift:46:14));
when use_scale = 13;
return %char(%dech(packed_data/d_shift:46:13));
when use_scale = 12;
return %char(%dech(packed_data/d_shift:46:12));
when use_scale = 11;
return %char(%dech(packed_data/d_shift:46:11));
when use_scale = 10;
return %char(%dech(packed_data/d_shift:46:10));
when use_scale = 9;
return %char(%dech(packed_data/d_shift:46:9));
when use_scale = 8;
return %char(%dech(packed_data/d_shift:46:8));
when use_scale = 7;
return %char(%dech(packed_data/d_shift:46:7));
when use_scale = 6;
return %char(%dech(packed_data/d_shift:46:6));
when use_scale = 5;
return %char(%dech(packed_data/d_shift:46:5));
when use_scale = 4;
return %char(%dech(packed_data/d_shift:46:4));
when use_scale = 3;
return %char(%dech(packed_data/d_shift:46:3));
when use_scale = 2;
return %char(%dech(packed_data/d_shift:46:2));
when use_scale = 1;
return %char(%dech(packed_data/d_shift:46:1));
endsl;
return %char(%dech(number_data:46:0));
Such replication of code is nothing but an eye-sore. How much simpler and clearer if one could just do the following, instead?
return %char(packed_data/d_shift:%len(packed_data):use_scale);
IBM does not intend to provide a solution to this request at this time, so it is being closed.
It is not possible to dynamically control the precision and scale of the first operand of %CHAR. RPG is a compiled language, so the precision and scale of a numeric expression must be known at compile time.
If %CHAR had additional precision and scale parameters, they could only affect the number of decimal positions in the result. This can be achieved relatively easily by post-processing on the result of %CHAR by locating the decimal point with %SCAN and then using %SUBST to eliminate unwanted decimal places.
Is it maybe possible to simply use %EDITC(numeric : editword) where you have your decimal in the editword.
I think you solution with doin it in the %dech with decimals is driving you further and further away from your use case.