Home The Company Publications Products Links Tips

Tips, Tricks, and Techniques

Last update: 30 April 2004

Dividing

"Arithmetic Curiosity"

We have come across a very interesting - and very disturbing - phenomenon in Natural regarding its computational functionality.
We run the following program (simplified for ease of reading):
DEFINE DATA
LOCAL
1 ##A         (N9.2) INIT <1000000.02>
1 #BB         (N3.3) INIT <3.606>
1 #CC         (N3.3) INIT <4.143>
1 #DD         (N5.4) INIT <143.7>
1 #EE         (N5.4) INIT <3.5>
1 #FF         (N6.4) INIT <152.3>
1 #GG         (N5.4) INIT <3.5>
1 #HH         (P13.2)
END-DEFINE
*
COMPUTE #HH =
    ##A * ( ( 1 +  #BB / 100 ) * #GG / #EE
     - (1 + #CC / 100 ) * #FF / #DD  )
WRITE #HH
END
and receive the following result:
NEXT
Page      1

        -67300.60
Then we make the following change to the program (adding the field #II as a temporary receiving field):
DEFINE DATA
LOCAL
1 ##A         (N9.2) INIT <1000000.02>
1 #BB         (N3.3) INIT <3.606>
1 #CC         (N3.3) INIT <4.143>
1 #DD         (N5.4) INIT <143.7>
1 #EE         (N5.4) INIT <3.5>
1 #FF         (N6.4) INIT <152.3>
1 #GG         (N5.4) INIT <3.5>
1 #HH         (P13.2)
1 #II         (P13.5)
END-DEFINE
*
COMPUTE #II =
    ##A * ( ( 1 +  #BB / 100 ) * #GG / #EE
     - (1 + #CC / 100 ) * #FF / #DD  )
ASSIGN #HH = #II
WRITE #HH
END
and re-execute, obtaining the following result:

NEXT
Page      1

        -67696.30
Why is there such a large discrepancy in the results? As far as I can recall (and have been told), Cobol does not act this way. Is this a bug, or a known pitfall of Natural that every experienced Natural programmer is familiar with and knows to avoid?
Regards,
Shlomo Godick
DBA, Mehish Computer Services, Ltd.
15 Lincoln St.
67134 Tel Aviv, Israel
Tel: 972-3-563-4407/4497
Fax: 972-3-561-1342
Email: shlomog@ibm.net

Here is an interseting follow-up to the previous computation problem I presented yesterday.
As you recall, the program was:
DEFINE DATA
LOCAL
1 ##A         (N9.2) INIT <1000000.02>
1 #BB         (N3.3) INIT <3.606>
1 #CC         (N3.3) INIT <4.143>
1 #DD         (N5.4) INIT <143.7>
1 #EE         (N5.4) INIT <3.5>
1 #FF         (N6.4) INIT <152.3>
1 #GG         (N5.4) INIT <3.5>
1 #HH         (P13.2)
END-DEFINE
*
COMPUTE #HH =
    ##A * ( ( 1 +  #BB / 100 ) * #GG / #EE
     - (1 + #CC / 100 ) * #FF / #DD  )
WRITE #HH
END

and we received the following (incorrect) result:
NEXT
Page      1

        -67300.60

The Natural programmer that showed me this now informs me that if, in the calculation, he multiplies by .01 instead of dividing by 100, as in the following:

DEFINE DATA
LOCAL
1 ##A         (N9.2) INIT <1000000.02>
1 #BB         (N3.3) INIT <3.606>
1 #CC         (N3.3) INIT <4.143>
1 #DD         (N5.4) INIT <143.7>
1 #EE         (N5.4) INIT <3.5>
1 #FF         (N6.4) INIT <152.3>
1 #GG         (N5.4) INIT <3.5>
1 #HH         (P13.2)
END-DEFINE
*
COMPUTE #HH =
    ##A * ( ( 1 +  #BB * .01 ) * #GG / #EE
     - (1 + #CC * .01 ) * #FF / #DD  )
WRITE #HH
END
he receives the following (correct) result:
NEXT
Page      1

        -67696.30
In other words, while defining all variables with the same precison helps to overcome the problem, it is not the real source of the problem. Rather, the division operation seems to be the culprit. In my opinion this is a bug and Natural, like Cobol, should provide internally an intermediate work field of sufficient precision to overcome the division operation problem. This would have been preferable to rewriting the PC version to compute the result incorrectly like the mainframe version (a good example of where even the zeal for cross-platform compatibility can be misapplied).
This problem really points to a more philosophical problem with Natural. Natural claims to be a 4GL, yet the need to be aware of precision issues in simple computations in order to get the correct result reduces it to a status below that of Cobol. In what other language (aside from Assembler) does a programmer have to do this? Remember, I am not talking about fine-tuning the code for performance (where looking at precision, packed numbers, etc. is appropriate), I'm talking about getting the correct as opposed to a grossly incorrect result!
Not to mention the public relations aspect. As DBA's, we often find ourselves acting as "good will ambassadors" for Adabas and Natural in our respective places of work. When the programmer told me that if he had been in charge of acquiring Natural and had been shown this bug before the purchase, he would not have acquired it - what was I to say to him?
My opinion only ...
Regards,
Shlomo Godick

Shlomo,
The following may help explain your arithmetic curiosity.
Edmund
0010 * -------+---------+---------+---------+---------+---------+---------+
0020 *
0030 * Dividing
0040 *
0050 * -------+---------+---------+---------+---------+---------+---------+
0060 *
0070 * The number of decimal positions resulting from a division in a
0080 * COMPUTE statement is derived from the first operand (dividend)
0090 * or the first result field. If the first result field has more
0100 * decimal positions than the operands, the number of decimal positions
0110 * in the first result field will be used.
0120 * (NATURAL 2.2 Reference Manual, p 3-87)
0130 *
0140 * -------+---------+---------+---------+---------+---------+---------+
0150 *
0160   DEFINE DATA
0170 *
0180   LOCAL
0190 *
0200      01 #A1                             (P1.0)    INIT <1>
0210      01 #A2                             (P1.4)    INIT <1>
0220      01 #B                              (P1.0)    INIT <3>
0230      01 #C                              (P6.2)
0240      01 #D                              (P6.6)
0250 *
0260   END-DEFINE
0270 *
0280 * -------+---------+---------+---------+---------+---------+---------+
0290 *
0300   COMPUTE #C = (#A1 / #B) * 1000000
0310   COMPUTE #D = (#A1 / #B) * 1000000
0320 *
0330   WRITE #C #D
0340 *
0350   COMPUTE #C = (#A2 / #B) * 1000000
0360   COMPUTE #D = (#A2 / #B) * 1000000
0370 *
0380   WRITE #C #D
0390 *
0400 * -------+---------+---------+---------+---------+---------+---------+
0410 *
0420   END
0430 *
0440 * -------+---------+---------+---------+---------+---------+---------+


Back to NATURAL Tips, Tricks, Techniques -- Overview