IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

CONDITIONAL USING COMP-2 WITH PROBLEMS.


IBM Mainframe Forums -> COBOL Programming
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
JOSUEGENTIL

New User


Joined: 05 May 2016
Posts: 1
Location: BRAZIL

PostPosted: Wed Nov 08, 2017 11:13 pm
Reply with quote

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.
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


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

PostPosted: Wed Nov 08, 2017 11:16 pm
Reply with quote

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).
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2010
Location: USA

PostPosted: Thu Nov 09, 2017 4:19 am
Reply with quote

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.
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2010
Location: USA

PostPosted: Thu Nov 09, 2017 4:41 am
Reply with quote

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)
Back to top
View user's profile Send private message
steve-myers

Active Member


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

PostPosted: Thu Nov 09, 2017 7:27 am
Reply with quote

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
Back to top
View user's profile Send private message
steve-myers

Active Member


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

PostPosted: Thu Nov 09, 2017 8:45 am
Reply with quote

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
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2010
Location: USA

PostPosted: Fri Nov 10, 2017 12:02 am
Reply with quote

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?
Back to top
View user's profile Send private message
steve-myers

Active Member


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

PostPosted: Fri Nov 10, 2017 6:06 am
Reply with quote

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.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> COBOL Programming

 


Similar Topics
Topic Forum Replies
No new posts C++ problems Java & MQSeries 3
No new posts COBOL - Move S9(11)v9(7) COMP-3 to -(... COBOL Programming 5
No new posts MFT File transfer problems All Other Mainframe Topics 5
No new posts Conditional EATTR in MFS ? IMS DB/DC 0
No new posts Converting ASCII values to COMP-3 (ZD... JCL & VSAM 2
Search our Forums:

Back to Top