[NEWSboard IBMi Forum]
  1. #1
    Registriert seit
    Jan 2003
    Beiträge
    118

    Rechenproblem in RPG

    Hallo Forum,

    uns ist ein Problem beim Rechnen in RPG aufgefallen; vielleicht weiß einer von euch, woran es liegt.

    RPG-Quelltext:

    DFELD1 S 11 2 INZ
    DFELD2 S 11 2 INZ
    DERGEBNIS S 6 2 INZ
    *
    C EVAL FELD1 = 360262,60
    C EVAL FELD2 = 442040,00
    *
    C EVAL ERGEBNIS = FELD1 /
    C (FELD2 / 100)
    C ERGEBNIS DSPLY
    *
    C EVAL ERGEBNIS = (FELD1 /
    C FELD2) * 100
    C ERGEBNIS DSPLY
    *
    C EVAL *INLR = *ON

    Im ersten Fall ist das Ergebnis bei uns 81,0 und im zweiten Fall ist das Ergebnis 81,5.
    Das korrekte Ergebnis ist 81,5.

    Was machen wir falsch?

    Vielen Dank für eure Unterstützung.

    Jo

    PS: Wir haben OS/400 V5R2.

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    Naja, eigentlich gar nichts. Das Problem ist, dass RPG bei Zwischenergebnissen die Feldausprägung der Felder übernimmt und nicht rundet !

    Sollen Zwischenergebnisse in größerer Genauigkeit erfolgen, muss man leider wie früher zu Hilfsfeldern greifen.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  3. #3
    Registriert seit
    Jan 2003
    Beiträge
    118
    Hallo Fuerchau,

    danke für die schnelle Antwort.

    Aber wenn ich doch 442040,00 durch 100 teile, bekomme ich 4420,40 raus; das passt in das ursprüngliche Feld und es muss auch nichts gerundet werden; es funktioniert auch dann nicht, wenn wir größere Felder (mit mehr Nachkommastellen) verwenden. Gibt es eventuell ein RPG-Problem bei der Abarbeitung der EVAL-Anweisung?

    Jo

  4. #4
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    Das Problem hier ist, dass die Zahl "100" keine Nachkomma hat, das Zwischenergebnis damit auch nicht, da das letzte Feld (in diesem Fall Konstante) genommen wird !

    Statt " / 100" kann auch " * 0.01" verwendet werden (Mult ist übrigens immer schneller als Div) um die Anzahl NK zu erweitern.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  5. #5
    Registriert seit
    May 2002
    Beiträge
    2.643

    Kommastellen

    Hallo Jo,
    bei der IBM gibt es dies dazu:

    http://www-912.ibm.com/a_dir/as4ptf....ht=0,eval,r520

  6. #6
    Registriert seit
    Jan 2003
    Beiträge
    118
    Hallo Furchau, hallo Tarasik,

    vielen Dank für eure Antworten.

    @Fuerchau:
    Jetzt ist es mir klar; wenn ich die Konstante 100,00 verwende, dann hat es funktioniert.

    @Tarasik:
    Ich werde mir das PTF besorgen und dann testen.

    Nochmals vielen Dank.

    Jo

  7. #7
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    Das PTF hat mit diesem "Problem" überhaupt nichts zu tun sondern betrifft die reine Fließkomma-Arithmetik.
    Im ILE-RPG-Reference-Handbuch wird ausführlich die Berechnung von Zwischenergebnissen erklärt.
    Für kaufmännische Berechnungen stört mich am meisten die fehlende Rundung der Zwischenergebnisse.


    Precision Rules for Numeric Operations
    Unlike the fixed-form operation codes where you must always specify the result of
    each individual operation, RPG must determine the format and precision of the
    result of each operation within an expression.
    If an operation has a result of format float, integer, or unsigned the precision is the
    maximum size for that format. Integer and unsigned operations produce 4-byte
    values and float operations produce 8-byte values.
    However, if the operation has a packed-decimal, zoned decimal, or binary format,
    the precision of the result depends on the precisions of the operands.
    It is important to be aware of the precision rules for decimal operations since even
    a relatively simple expression may have a result that may not be what you expect.
    For example, if the two operands of a multiplication are large enough, the result of
    the multiplication will have zero decimal places. If you are multiplying two 20
    digit numbers, ideally you would need a 40 digit result to hold all possible results
    of the multiplication. However, since RPG supports numeric values only up to 31
    digits, the result is adjusted to 31 digits. In this case, as many as 10 decimal digits
    are dropped from the result.
    There are two sets of precision rules that you can use to control the sizes of
    intermediate values:
    1. The default rules give you intermediate results that are as large as possible in
    order to minimize the possibility of numeric overflow. Unfortunately, in certain
    cases, this may yield results with zero decimal places if the result is very large.
    2. The ″Result Decimal Positions″ precision rule works the same as the default
    rule except that if the statement involves an assignment to a numeric variable
    or a conversion to a specific decimal precision, the number of decimal positions
    of any intermediate result is never reduced below the desired result decimal
    places.
    In practice, you don’t have to worry about the exact precisions if you examine
    the compile listing when coding numeric expressions. A diagnostic message
    indicates that decimal positions are being dropped in an intermediate result. If
    there is an assignment involved in the expression, you can ensure that the
    decimal positions are kept by using the ″Result Decimal Positions″ precision
    rule for the statement by coding operation code extender (R).
    If the ″Result Decimal Position″ precision rule cannot be used (say, in a
    relational expression), built-in function %DEC can be used to convert the result
    of a sub-expression to a smaller precision which may prevent the decimal
    positions from being lost.
    Using the Default Precision Rules
    Using the default precision rule, the precision of a decimal intermediate in an
    expression is computed to minimize the possibility of numeric overflow. However,
    if the expression involves several operations on large decimal numbers, the
    intermediates may end up with zero decimal positions. (Especially, if the
    expression has two or more nested divisions.) This may not be what the
    programmer expects, especially in an assignment.
    When determining the precision of a decimal intermediate, two steps occur:
    1. The desired or ″natural″ precision of the result is computed.
    Precision Rules for Numeric Operations
    2. If the natural precision is greater than 31 digits, the precision is adjusted to fit
    in 31 digits. This normally involves first reducing the number of decimal
    positions, and then if necessary, reducing the total number of digits of the
    intermediate.
    This behaviour is the default and can be specified for an entire module (using
    control specification keyword EXPROPTS(*MAXDIGITS) or for single free-form
    expressions (using operation code extender M).
    Precision of Intermediate Results
    Table 52 describes the default precision rules in more detail.
    Table 52. Precision of Intermediate Results
    Operation Result Precision
    Note: The following operations produce a numeric result. L1 and L2 are the number of
    digits of the two operands. Lr is the number of digits of the result. D1 and D2 are the
    number of decimal places of the two operands. Dr is the number of decimal places of the
    result. T is a temporary value.
    N1+N2 T=min (max (L1-D1, L2-D2)+1, 31)
    Dr=min (max (D1,D2), 31-t)
    Lr=t+Dr
    N1-N2 T=min (max (L1-D1, L2-D2)+1, 31)
    Dr=min (max (D1,D2), 31-t)
    Lr=t+Dr
    N1*N2 Lr=min (L1+L2, 31)
    Dr=min (D1+D2, 31-min ((L1-D1)+(L2-D2), 31))
    N1/N2 Lr=31
    Dr=max (31-((L1-D1)+D2), 0)
    N1**N2 Double float
    Note: The following operations produce a character result. Ln represents the length of the
    operand in number of characters.
    C1+C2 Lr=min(L1+L2,65535)
    Note: The following operations produce a DBCS result. Ln represents the length of the
    operand in number of DBCS characters.
    D1+D2 Lr=min(L1+L2,16383)
    Note: The following operations produce a result of type character with subtype indicator.
    The result is always an indicator value (1 character).
    V1=V2 1 (indicator)
    V1>=V2 1 (indicator)
    V1>V2 1 (indicator)
    V1<=V2 1 (indicator)
    V1<V2 1 (indicator)
    V1<>V2 1 (indicator)
    V1 AND V2 1 (indicator)
    V1 OR V2 1 (indicator)
    Precision Rules for Numeric Operations
    Chapter 21. Expressions 429
    Example of Default Precision Rules
    This example shows how the default precision rules work.
    When the above Calculation specification is processed, the resulting value assigned
    to FLD1 will have a precision of zero decimals, not the three decimals expected.
    The reason is that when it gets to the last evaluation (4 in the above example),
    the number to which the factor is scaled is negative. To see why, look at how the
    expression is evaluated.
    1 Evaluate FLD3/100
    Rules:
    Lr = 31
    Dr = max(31-((L1-D1)+D2),0)
    = max(31-((5-2)+0),0)
    = max(31-3,0)
    = 28
    2 Evaluate (Result of 1 * FLD4)
    Rules:
    Lr = min(L1+L2,31)
    = min(31+9,31)
    = 31
    Dr = min(D1+D2,31-min((L1-D1)+(L2-D2),31))
    = min(28+4,31-min((30-28)+(9-4),31))
    = min(32,31-min(4+5,31)
    = min(32,22)
    = 22
    3 Evaluate (Result of 2 + FLD5)
    Rules:
    T = min(max(L1-D1,L2-D2)+1,31)
    = min(max(31-22,9-4)+1,31)
    = min(max(9,5)+1,31)
    = min(10,30)
    = 10
    Dr = min(max(D1,D2),31-T)
    = min(max(22,4),31-10)
    = min(22,21)
    = 21
    Lr = T + Dr
    = 10 + 21 = 31
    4 Evaluate FLD2/Result of 3
    Rules:
    DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++++
    D FLD1 S 15P 4
    D FLD2 S 15P 2
    D FLD3 S 5P 2
    D FLD4 S 9P 4
    D FLD5 S 9P 4
    CL0N01Factor1+++++++Opcode(E)+Extended-factor2+++++++++++++++++++++++++++
    C EVAL FLD1 = FLD2/(((FLD3/100)*FLD4)+FLD5)
    ( 1 )
    ( 2 )
    ( 3 )
    ( 4 )
    Figure 160. Precision of Intermediate Results
    Precision Rules for Numeric Operations
    Lr = 31
    Dr = max(31-((L1-D1)+D2),0)
    = max(31-((15-2)+ 21),0)
    = max(31-(13+21),0)
    = max(-3,0) **** NEGATIVE NUMBER TO WHICH FACTOR IS SCALED ****
    = 0
    To avoid this problem, you can change the above expression so that the first
    evaluation is a multiplication rather than a division, that is, FLD3 * 0.01 or use the
    %DEC built-in function to set the sub-expression FLD3/100: %DEC(FLD3/100 : 15 :
    4) or use operation extender (R) to ensure that the number of decimal positions
    never falls below 4.
    Using the ″Result Decimal Position″ Precision Rules
    The ″Result Decimal Position″ precision rule means that the precision of a decimal
    intermediate will be computed such that the number of decimal places will never
    be reduced smaller than the number of decimal positions of the result of the
    assignment. This is specified by:
    1. EXPROPTS(*RESDECPOS) on the Control Specification. Use this to specify
    this behaviour for an entire module.
    2. Operation code extender R specified for a free-form operation.
    Result Decimal Position rules apply in the following circumstances:
    1. Result Decimal Position precision rules apply only to packed decimal
    intermediate results. This behaviour does not apply to the intermediate results
    of operations that have integer, unsigned, or float results.
    2. Result Decimal Position precision rules apply only where there is an
    assignment (either explicit or implicit) to a decimal target (packed, zoned, or
    binary). This can occur in the following situations:
    a. For an EVAL statement, the minimum decimal places is given by the
    decimal positions of the target of the assignment and applies to the
    expression on the right-hand side of the assignment. If half-adjust also
    applies to the statement, one extra digit is added to the minimum decimal
    positions (provided that the minimum is less than 31).
    b. For a RETURN statement, the minimum decimal places is given by the
    decimal positions of the return value defined on the PI specification for the
    procedure. If half-adjust also applies to the statement, one extra digit is
    added to the minimum decimal positions (provided that the minimum is
    less than 31).
    c. For a VALUE or CONST parameter, the minimum decimal positions is
    given by the decimal positions of the formal parameter (specified on the
    procedure prototype) and applies to the expression specified as the passed
    parameter.
    d. For built-in function %DEC and %DECH with explicit length and decimal
    positions specified, the minimum decimal positions is given by the third
    parameter of the built-in function and applies to the expression specified as
    the first parameter.
    The minimum number of decimal positions applies to the entire sub-expression
    unless overridden by another of the above operations. If half-adjust is specified
    (either as the H operation code extender, or by built-in function %DECH), the
    number of decimal positions of the intermediate result is never reduced below
    N+1, where N is the number of decimal positions of the result.
    Precision Rules for Numeric Operations
    Chapter 21. Expressions 431
    3. The Result Decimal Position rules do not normally apply to conditional
    expressions since there is no corresponding result. (If the comparisons must be
    performed to a particular precision, then %DEC or %DECH must be used on
    the two arguments.)
    On the other hand, if the conditional expression is embedded within an
    expression for which the minimum decimal positions are given (using one of
    the above techniques), then the Result Decimal Positions rules do apply.
    Example of ″Result Decimal Position″ Precision Rules
    The following examples illustrate the ″Result Decimal Position″ precision rules:
    *..1....+....2....+....3....+....4....+....5....+. ...6....+....7...+....
    * This example shows the precision of the intermediate values
    * using the two precision rules.
    D p1 s 13p 2
    D p2 s 13p 2
    D p3 s 13p 2
    D p4 s 15p 9
    D s1 s 13s 2
    D s2 s 13s 2
    D i1 s 10i 0
    D f1 s 8f
    D proc pr 8p 3
    D parm1 20p 5 value
    * In the following examples, for each sub-expression,
    * two precisions are shown. First, the natural precision,
    * and then the adjusted precision.
    * Example 1:
    /FREE
    eval p1 = p1 * p2 * p3;
    // p1*p2 -> P(26,4); P(26,4)
    // p1*p2*p3 -> P(39,6); P(31,0) (decimal positions are truncated)
    eval(r) p1 = p1 * p2 * p3;
    // p1*p2 -> P(26,4); P(26,4)
    // p1*p2*p3 -> P(39,6); P(31,2) (decimal positions do not drop
    // below target decimal positions)
    eval(rh)p1 = p1 * p2 * p3;
    // p1*p2 -> P(26,4); P(26,5)
    // p1*p2*p3 -> P(39,6); P(31,3) (decimal positions do not drop
    // below target decimals + 1)
    // Example 2:
    eval p4 = p1 * p2 * proc (s1*s2*p4);
    // p1*p2 -> P(26,4); P(26,4)
    // s1*s2 -> P(26,4); P(26,4)
    // s1*s2*p4 -> P(41,13); P(31,3) (decimal positions are truncated)
    // p1*p2*proc() -> P(34,7); P(31,4) (decimal positions are truncated)
    eval(r) p4 = p1 * p2 * proc (s1*s2*p4);
    // p1*p2 -> P(26,4); P(26,4)
    // s1*s2 -> P(26,4); P(26,4)
    // s1*s2*p4 -> P(41,13); P(31,5)
    // p1*p2*proc() -> P(34,7); P(31,7) (we keep all decimals since we are
    // already below target decimals)
    /END-FREE
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  8. #8
    KM is offline [professional_User]
    Registriert seit
    Apr 2003
    Beiträge
    1.012
    Hallo Jo,

    warum benutzt Du nicht einfach den EVAL(R) ? Dieser rechnet richtig, egal wieviele Nachkommastellen vorhanden sind.

    Gruß,
    KM

  9. #9
    Registriert seit
    Mar 2002
    Beiträge
    5.365
    Hallo jo400,

    Zitat Zitat von jo400
    Hallo Forum,

    Was machen wir falsch?

    Jo

    PS: Wir haben OS/400 V5R2.
    Ihr verwendet Literale (100) beim Rechnen, das gibt mit allen Compilern der Welt Randprobleme.

    mfg

    Dieter Bender
    AS400 Freeware
    http://www.bender-dv.de
    Mit embedded SQL in RPG auf Datenbanken von ADABAS bis XBASE zugreifen
    http://sourceforge.net/projects/appserver4rpg/

  10. #10
    Registriert seit
    Feb 2001
    Beiträge
    20.695
    Ausgenommen Sprachen, die den Feldtyp "Dezimal" nicht kennen und immer nur mit Float/Double rechnen. Hier sind die Probleme mit den Nachkommastellen viel gravierenden:
    Dezimal: 3 * 3.33 = 9.99
    Double: 3 * 3.33 = 10.000000000001

    Und dann wundert man sich immer warum rechnet der nur so komisch ?!
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

Similar Threads

  1. RPG: Client Infos lesen?
    By robertki in forum NEWSboard Programmierung
    Antworten: 25
    Letzter Beitrag: 19-01-07, 08:42
  2. Bibliotheksliste in RPG IV abfragen
    By timeless in forum IBM i Hauptforum
    Antworten: 5
    Letzter Beitrag: 11-01-07, 12:04
  3. Problem mit Java-Methoden Aufruf aus ILE RPG?
    By Stoeberl in forum NEWSboard Programmierung
    Antworten: 8
    Letzter Beitrag: 10-01-07, 10:58
  4. RPG goes Web
    By jth in forum NEWSboard Programmierung
    Antworten: 1
    Letzter Beitrag: 21-12-06, 11:13

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • You may not post attachments
  • You may not edit your posts
  •