|
Thanks Scott,
I had a feeling it was something like that.
When you explained the "internal workings" of the operation, it made even more sense.
In your professional opinion, would it be better to use the %dec bif or the Eval(R) op-code.
Thanks,
Jeff Young Sr. Programmer Analyst
IBM -e(logo) server Certified Systems Exper - iSeries Technical Solutions V5R2 IBM Certified Specialist- e(logo) server i5Series Technical Solutions Designer V5R3
IBM Certified Specialist- e(logo)server i5Series Technical Solutions Implementer V5R3
________________________________
From: Scott Klement <rpg400-l@xxxxxxxxxxxxxxxx>
To: RPG programming on the IBM i / System i <rpg400-l@xxxxxxxxxxxx>
Sent: Monday, August 10, 2009 2:00:10 PM
Subject: Re: EVAL(H) Question
Hi Jeff,
By default, RPG uses something called "the Maximum Digits rule" for decimal precision in the intermediate results of an expression. Which basically means that RPG needs to create temporary (under-the-covers) variables for each step in calculating your expression.
First thing RPG has to do is take Srp_Value_Rate and divide it by 100. So Srp_Value_Rate is a 5,2 field... and 100 is a 3-digit field. What's the maximum possible digits to the left of the decimal place when dividing a 5,2 by a 3,0 field? still 3 digits, right? There are no decimal places in a 3,0 field, so division can't make the number higher.
So, since you can only have max 3-digits to the left of the decimal place, the intermediate result will be 30,27 by default (30 digits with 27 decimal places). And if Srp_Value_rate=40, that means you'll have
Srp_Value_Rate / 100
000.400000000000000000000000000
Now subtract that value from 1. So you have a 1,0 field subtracting a 30,27 field? Whats the max digits to the left of the decimal place? it's one higher, because it could potentially overflow into a 4th digit (-9 - -999 = -1018) so you'll now have a 30,26 intermediate result
1 - (Srp_Value_Rate / 100)
000.600000000000000000000000000
This is silly because you don't *need* 26 decimal places here -- but RPG thinks you do. You really only need 2.
Now RPG needs to divide Current_Srp_Value by that intermediate result. (Dividing by an intermediate result is often messy because RPG maxes out the decimal places using the *MAXDIGITS style, which means the digits to the left goes through the roof).
So you hae a 11,4 field divided by a 30,26 field. How many maximum digits to the left? The maximum possible value of a 11,4 divided by a 30,26 would be yikes, 37 digits to the left of the decimal place? That won't fit into RPG's default 30 digit intermediate result fields, so it'll eliminate all of the decimal places so that, at least the whole numbers will be preserved.
current_base / (1 - (Srp_Value_Rate / 100))
000000000000000000000000000004
So that's what RPG is doing under the covers -- and is the reason why you're having this problem. At first glance, it might sound like increasing the size of the intermediate field from 30 digits to 63 digits might help -- but it won't. Because the intermediate result of the first two calculations will end up being 59 decimal places instead of 26, thus creating the same problem (just in a larger field)
Personally, I'd solve the problem by doing this:
eval(h) current_srp_value = Current_base
/ %dec(1 - (Srp_Value_rate/100): 6: 2);
I've used the %DEC() BIF to control the size of the intermediate result. I've told RPG that the intermediate result of the first two steps of the
expression should be a 6,2 field -- that way, it won't calculate 26 decimal positions in the intermdiate result.
Then the final division results in a maximum of 13 digit intermediate field, leaving 17 decimal positions, more than enough space for your purposes, and the EVAL(H) then rounds it off to 2 decimal places, as you'd expect.
That's the optimal solution -- but requires someone to sit down and figure out what RPG is doing in order to know where to put the %DEC() and know how big to make it. So it requires a total geek like me. :) I mean, really, who does that???
An easier solution is to specify EXPROPTS(*RESDECPOS) on the H-spec, or the R extender on the EVAL. In either case, that tells RPG not to drop all of it's decimal places for it's intermediate result fields. Instead, it'll force the intermediates to have as many decimal places as the result.
eval(hr) current_srp_value = Current_base
/ (1 - (Srp_Value_rate/100));
Have a lovely day.
Jeff Young wrote:
I have the following instruction in my program:
Eval(H) Current_SRP_Value = Current_Base / (1 - (SRP_Value_Rate / 100));
ATTR current_srp_value TYPE = PACKED(9,2), LENGTH = 5 BYTES ATTR current_base TYPE = PACKED(11,4), LENGTH = 6 BYTES ATTR srp_value_rate TYPE = PACKED(5,2), LENGTH = 3 BYTES
EVAL SRP_Value_Rate SRP_VALUE_RATE = 040.00 EVAL Current_Base CURRENT_BASE = 0000002.7938
The result being returned is 4.00.
When using a calculator, I get the value 4.6563333333333333.
I would expect the result to be 4.66.
Do I need to specify Eval(RH) to get the desired result?
I am on V5R4.
Thanks,
Jeff Young Sr. Programmer Analyst
IBM -e(logo) server Certified Systems Exper - iSeries Technical Solutions V5R2 IBM Certified Specialist- e(logo) server i5Series Technical Solutions Designer V5R3
IBM Certified Specialist- e(logo)server i5Series Technical Solutions Implementer V5R3
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.