# CONDITIONAL USING COMP-2 WITH PROBLEMS.

Author Message
JOSUEGENTIL

New User

Joined: 05 May 2016
Posts: 1
Location: BRAZIL

 Posted: Wed Nov 08, 2017 11:13 pm In a COBOL ENTERPRISE program, using COMP-2 and decimal fields, I´m having problem using the conditional IF field-comp2 EQUAL 100: CP-1 USAGE COMP-2 VALUE 99.99. CP-2 USAGE COMP-2 VALUE 00.01. CP-SUM USAGE COMP-2 VALUE 0. CP-SUM-DEC PIC S9(003)V(006) VALUE 0. ... ADD CP-1 TO CP-SUM ADD CP-2 TO CP-SUM IF CP-SUM EQUAL 100 ... ELSE ... Altough the sum of 99.99 + 00.01 gives 100 as a result, the ELSE is being applied. If I do the same replacint CP-SUM for CP-SUM-DEC, then the IF statement is correctly applied. Can anyone help me to understand why the comparison EQUAL works for a decimal field but not for a comp-2, in this case? Thanks in advane.
Robert Sample

Global Moderator

Joined: 06 Jun 2008
Posts: 8589
Location: Dubuque, Iowa, USA

Posted: Wed Nov 08, 2017 11:16 pm

COMP-2 variables are floating point; it would be rare indeed for them to be EXACTLY any particular value. When I ran the equivalent to your code:
 Code: 77  CP-1 USAGE COMP-2.                     77  CP-2 USAGE COMP-2.                     77  CP-SUM USAGE COMP-2 VALUE 0.           77  CP-SUM-DEC PIC S9(003)V9(006) VALUE 0. *                                           PROCEDURE DIVISION.                         1000-START.                                     MOVE 99.99                   TO  CP-1.      MOVE  0.01                   TO  CP-2.      ADD CP-1 TO CP-SUM.                         ADD CP-2 TO CP-SUM.                         DISPLAY '>' CP-SUM '<'.
I got results of:
 Code: > .99999999999999996E 02<
Which can be explained as the way COBOL handles intermediate precision for floating point values.

Also, when you post code use the CODE tag for readability. And post working code, not something you cobbled together for this web site. I compiled your code under Enterprise COBOL 5.1.1, and I got 3 errors in the compile: CP-1 and CP-2 VALUE clauses were not valid, and your use of a replication factor in CP-SUM-DEC is not valid (you did NOT put V9(006) which is what COBOL expects -- V(006) as you posted means you want six implied decimal points).
sergeyken
Warnings : 2

Senior Member

Joined: 29 Apr 2008
Posts: 1228

Posted: Thu Nov 09, 2017 4:19 am

 JOSUEGENTIL wrote: In a COBOL ENTERPRISE program, using COMP-2 and decimal fields, I´m having problem using the conditional IF field-comp2 EQUAL 100: CP-1 USAGE COMP-2 VALUE 99.99. CP-2 USAGE COMP-2 VALUE 00.01. CP-SUM USAGE COMP-2 VALUE 0. CP-SUM-DEC PIC S9(003)V(006) VALUE 0. ... ADD CP-1 TO CP-SUM ADD CP-2 TO CP-SUM IF CP-SUM EQUAL 100 ... ELSE ... Although the sum of 99.99 + 00.01 gives 100 as a result, the ELSE is being applied. If I do the same replacing CP-SUM for CP-SUM-DEC, then the IF statement is correctly applied. Can anyone help me to understand why the comparison EQUAL works for a decimal field but not for a comp-2, in this case? Thanks in advance.

Obvious solution: before posting this question on the forum, it is a good idea just to print the actual value of CP-SUM, isn't it?

Floating point in mainframe is handled as binary fixed value, and binary power of the number. This obviously may cause rounding surprises. To avoid this, use any decimal form, like COMP-3, etc.
sergeyken
Warnings : 2

Senior Member

Joined: 29 Apr 2008
Posts: 1228

Posted: Thu Nov 09, 2017 4:41 am

AFAIU, the decimal 99.99 is represented in hex as X'63E6666666666666', with appropriate exponent.
The decimal 0.01 is represented as (normalized) X'10000000000000', with different exponent.

In order to sum two values they are shifted to corresponding binary point position, to make both exponents equal:
 Code: X'63E6666666666666' +X'0001000000000000' =X'63E7666666666666'
this is equivalent in decimal: 99. + something below 1.0, while the decimal 100.00 must be represented as X'6400000000000000'

(I may be wrong in details of binary conversion, but the idea is exactly as shown)
steve-myers

Active Member

Joined: 30 Nov 2013
Posts: 895
Location: The Universe

Posted: Thu Nov 09, 2017 7:27 am

Sergeyken is correct, though the hex values he shows are incorrect.

Back in the 1960s when I started this trade I did Fortran, on a different platform than S/360, and the fact that conversion of decimal fractions to binary floating point was not always "correct," so floating point comparison was not always "correct" was drummed into our heads.

I transformed the topic starter's program to Assembler, though I was not so foolish to try the comparison. and got this.
 Code: 000000                00000 00038     1 FP       CSECT                  R:F  00000           2          USING *,15 000000 6800 F018            00018     3          LD    0,CPSUM 000004 6A00 F020            00020     4          AD    0,CP1  000008 6A00 F028            00028     5          AD    0,CP2 00000C 6000 F018            00018     6          STD   0,CPSUM 000010 1BFF                           7          SR    15,15 000012 07FE                           8          BR    14 000014 00000000 000018 0000000000000000               9 CPSUM    DC    D'0' 000020 4263FD70A3D70A3D              10 CP1      DC    D'99.99' 000028 3F28F5C28F5C28F6              11 CP2      DC    D'0.01' 000030 4264000000000000              12 CP100    DC    D'100' 000000                               13          END   FP

Now I have observed HLASM's floating point conversion often runs 1 bit higher than most compiler's conversion so I cannot confidently state the hex values for CP1 and CP2 here are "correct" but it does illustrate the problem.

I did run this, and got this -
 Code: l (cp1 cp2 cp100 cpsum  CP1  +.99989999999999998 E+ 2                                       00000000  CP2  +.10000000000000000 E- 1                                       00000000  CP100  +.100 E+ 3                                                   00000000  CPSUM  +.99999999999999996 E+ 2                                     00000000  TEST l (cp1 cp2 cp100 cpsum) x  CP1                                                                 00000000         +0  4263FD70 A3D70A3D  CP2                                                                 00000000         +0  3F28F5C2 8F5C28F6  CP100                                                               00000000         +0  42640000 00000000                                                   CPSUM                                                               00000000         +0  4263FFFF FFFFFFFF
steve-myers

Active Member

Joined: 30 Nov 2013
Posts: 895
Location: The Universe

Posted: Thu Nov 09, 2017 8:45 am

For what it's worth, I did CP1 + CP2 like the hardware does it. First, it transforms CP2 to 4200028F5C28F5C2 so the exponents (the 42) are equal, and then adds the fractions in the usual way. Notice that the shift of CP2 discards bits; there is no rounding here.

Had this arithmetic been done with binary (IEEE) floating point there would be rounding in the shift, so there is a better chance that CP1 + CP2 would have resulted in 100.

I converted the program to run binary floating point, and it turned out my theory was correct.
 Code: Loc  Object Code    Addr1 Addr2  Stmt   Source Statement 000000                00000 00038     1 FP       CSECT                  R:F  00000           2          USING *,15 000000 6800 F018            00018     3          LD    0,CPSUM 000004 ED00 F020 001A       00020     4          ADB   0,CP1 00000A ED00 F028 001A       00028     5          ADB   0,CP2 000010 6000 F018            00018     6          STD   0,CPSUM 000014 1BFF                           7          SR    15,15    000016 07FE                           8          BR    14 000018 0000000000000000               9 CPSUM    DC    DB'0' 000020 4058FF5C28F5C28F              10 CP1      DC    DB'99.99' 000028 3F847AE147AE147B              11 CP2      DC    DB'0.01' 000030 4059000000000000              12 CP100    DC    DB'100' 000000                               13          END   FP

 Code: l (cp1 cp2 cpsum cp100) x  CP1         +0  4058FF5C 28F5C28F  CP2         +0  3F847AE1 47AE147B  CPSUM         +0  40590000 00000000  CP100         +0  40590000 00000000
sergeyken
Warnings : 2

Senior Member

Joined: 29 Apr 2008
Posts: 1228

Posted: Fri Nov 10, 2017 12:02 am

 steve-myers wrote: I converted the program to run binary floating point, and it turned out my theory was correct.

Good investigation!

Kindly, clarify for myself the idea of enhanced floating point formats, and rounding rules.

It is obvious how +100.00 in D format is represented as X'4264000000000000'
But it looks like +100.00 in DB format must be X'4019000000000000' (as shifted two bits right, with exponent reduced by 2)
Why it is actually X'4059000000000000'?
Where this single extra bit - X'0040000000000000' - comes from?
steve-myers

Active Member

Joined: 30 Nov 2013
Posts: 895
Location: The Universe

 Posted: Fri Nov 10, 2017 6:06 am z/Architecture supports two (actually three) floating point formats.The original System/360 floating point. This was actually pretty lousy. I've always thought it was added on very late in the game when someone, my theory has always been in marketing, realized, "My God, there's no floating point! How are we gonna sell this to the 709x and 704x crowd?" So the hardware people very hurriedly devised the cheapest possible (to implement) floating point. I remember analyzing this standard in 1966 and realized how lousy it was. In fact it was worse than my 1966 analysis revealed! One conclusion I did reach was in the real world you had to do everything in double precision because there were so few bits in single precision. It was so bad IBM was forced to spend I couldn't guess how many millions fixing the worse problems in the machines in the field in 1968."Binary" floating point. This is an implementation of the IEEE floating point standard which was formalized from the 8087 Intel coprocessing chip which now exists in every x86 chip Intel makes.Decimal floating point. I know very little about this other than it exists. There is a pretty decent discussion, far better than I can do, here.
 View Bookmarks All times are GMT + 6 Hours

 Topic Forum Replies Similar Topics How to add 2 digits to COMP-3 file? DFSORT/ICETOOL 11 Unable to display comp variable COBOL Programming 4 TSO initial setup / problems TSO/ISPF 9 Write 9(07) comp-3 data into output file DFSORT/ICETOOL 4 Conditional step execution based on P... JCL & VSAM 9
Search our Forums: