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

Rounding off to the next decimal number


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

New User


Joined: 05 Aug 2009
Posts: 44
Location: Hyderabad

PostPosted: Tue Mar 06, 2012 5:48 pm
Reply with quote

working on a Cobol requirement wherein I need to round of a computed value (defined as PIC S9(11)VA9(4) COMP-3) to the next 100th number.
For ex:
1) if the final computed value is 13333.33, it should be rounded off to 13400
2) if the final computed value is 10366.67, it should be rounded off to 10400
3) if the final computed value is 950, it should be rounded off to 1000
4) if the final computed value is 801, it should be rounded off to 900.
5) if the final computed value is 899, it should be rounded off to 900.

It would not be possible with rounded keyword. Can someone help me how do I need to proceed?

Thanks,
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: Tue Mar 06, 2012 6:00 pm
Reply with quote

First, get your terminology right -- you are NOT rounding; rounding involves both downward and upward changes.

Second, you need to be clearer -- what if the value is 10300? Does this become 10400?

Third, you can achieve what you want with two COBOL statements: a DIVIDE with REMAINDER followed by a test to see if the remainder is greater than zero and add 1 to the division result (or just add 1 if the number is always to be bumped up).
Back to top
View user's profile Send private message
prino

Senior Member


Joined: 07 Feb 2009
Posts: 1306
Location: Vilnius, Lithuania

PostPosted: Tue Mar 06, 2012 6:01 pm
Reply with quote

And what do you do with 100? Make it 200, because that is the next 100the {sic} number...

Code:
y = trunc(x / 100) * 100

if x ¬= y then
  x = trunc(x / 100) * 100 + 100
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Tue Mar 06, 2012 6:03 pm
Reply with quote

the A in PIC S9(11)VA9(4) COMP-3 has me confused.

also, this requirement
Quote:
4) if the final computed value is 801, it should be rounded off to 900.


would indicate that the following would suffice

divide the result by 100,
add 1
multiply by 100
and storing in PIC S9(11) comp-3

reminds me of a quote from the movie The Shooter:
Quote:
who dreams up this kind of bullshit anyway?
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: Tue Mar 06, 2012 6:18 pm
Reply with quote

Iassumed the A was a typo since the defintiion is not otherwise syntactically correct.

Dick, I like that quote -- and it applies to so many posts here! icon_biggrin.gif
Back to top
View user's profile Send private message
Phrzby Phil

Senior Member


Joined: 31 Oct 2006
Posts: 1042
Location: Richmond, Virginia

PostPosted: Tue Mar 06, 2012 6:23 pm
Reply with quote

Adding to earlier comments that you are not in fact "rounding," the position you are concerned with is not hundredth, but rather hundreds.
Back to top
View user's profile Send private message
chowdhrykapildev

New User


Joined: 05 Aug 2009
Posts: 44
Location: Hyderabad

PostPosted: Tue Mar 06, 2012 6:32 pm
Reply with quote

Hi,

Thanks for quick reply.
If the computed value is 10300, it should be retained to 10300. In the same way, if the compulted value is 100, it should be retained to 100.

Apologies, the A was a typo in the COMP3 definition. It is PIC S9(11)V9(4) COMP-3.

@dbzTHEdinosauer: The division, adding 1 and multiplying by 100 makes the same number (ex: 13333.37) to 13433.37. But the final result should be 13400 instead.
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Tue Mar 06, 2012 6:42 pm
Reply with quote

chowdhrykapildev,

FM! why do i even participate with rookies?

A = PIC S9(9) COMP-3
B = PIC S9(9) COMP-3
C = PIC S9(9) COMP-3

MOVE 13333.37 TO A
(A now contains 13333)
DIVIDE A BY 100 GIVING B
(B now contains 133)
ADD 1 TO B
(B now contains 134)
MULTIPLY B BY 100 GIVING C
(C now contains 13400)
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: Tue Mar 06, 2012 6:52 pm
Reply with quote

Quote:
@dbzTHEdinosauer: The division, adding 1 and multiplying by 100 makes the same number (ex: 13333.37) to 13433.37. But the final result should be 13400 instead.
Not if you know your COBOL. Code:
Code:
       77  WS-FULLDATA   PIC S9(11)V9(04).
       77  WS-INTDATA    PIC S9(11).
       77  WS-REMAINDER  PIC S9(11)V9(04).
       77  WS-FIXEDATA   PIC S9(11)V9(04).
       77  WS-DISPLAY1   PIC +9(11).9(04).
       77  WS-DISPLAY2   PIC +9(11).9(04).

       LINKAGE SECTION.
      /
       PROCEDURE DIVISION.
       S1000-MAIN       SECTION.
            MOVE 13333.33              TO  WS-FULLDATA.
            PERFORM 9999-CALCULATE.
            MOVE 10366.67              TO  WS-FULLDATA.
            PERFORM 9999-CALCULATE.
            MOVE 950                   TO  WS-FULLDATA.
            PERFORM 9999-CALCULATE.
            MOVE 801                   TO  WS-FULLDATA.
            PERFORM 9999-CALCULATE.
            MOVE 899                   TO  WS-FULLDATA.
            PERFORM 9999-CALCULATE.
            MOVE 800                   TO  WS-FULLDATA.
            PERFORM 9999-CALCULATE.
           GOBACK.
       9999-CALCULATE.
           DIVIDE WS-FULLDATA BY 100
               GIVING WS-INTDATA
               REMAINDER WS-REMAINDER.
           IF  WS-REMAINDER > ZERO
               ADD 1                  TO  WS-INTDATA
           END-IF.
           COMPUTE WS-FIXEDATA = WS-INTDATA * 100 .
           MOVE WS-FULLDATA           TO  WS-DISPLAY1.
           MOVE WS-FIXEDATA           TO  WS-DISPLAY2.
           DISPLAY WS-DISPLAY1 ' ' WS-DISPLAY2.
produces results of
Code:
 +00000013333.3300 +00000013400.0000
 +00000010366.6700 +00000010400.0000
 +00000000950.0000 +00000001000.0000
 +00000000801.0000 +00000000900.0000
 +00000000899.0000 +00000000900.0000
 +00000000800.0000 +00000000800.0000
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Tue Mar 06, 2012 7:23 pm
Reply with quote

Code:
01  comp-3-with-decimals comp-3 PIC S9(11)V9(4).

01  display-no-decimals PIC 9(11).
01  filler redefines display-no-decimals.
    05  filler PIC x(9).
    05  units-less-than-100 PIC 99.
        88 a-round-number-to-100-already VALUE ZERO.


Code:

MOVE comp-3-with-decimals TO display-no-decimals
IF NOT a-round-number-to-100-already
    MOVE ZERO TO units-less-than-100
    ADD 100 TO display-no-decimals
    MOVE display-no-decimals TO comp-3-with-decimals
END-IF


It would also be possible by redefining the comp-3.

Might be another way even simpler... checking....
Back to top
View user's profile Send private message
prino

Senior Member


Joined: 07 Feb 2009
Posts: 1306
Location: Vilnius, Lithuania

PostPosted: Tue Mar 06, 2012 8:06 pm
Reply with quote

Bless PL/I, with it's negative rounding:

Code:
dcl f fixed (7,3) init (1200.000);
dcl h fixed (7,3) init (0);
g = round(f + 49.999, -2);
put edit(f,g)(p'zzz9v.999', p'zzzzzz9');
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Tue Mar 06, 2012 8:24 pm
Reply with quote

In case you want to take account of th decimal part (ie .0001 goes to next highest 100).

Code:
01  comp-3-with-decimals comp-3 PIC S9(11)V9(4).

01  display-with-decimals PIC 9(11)V9(4).
01  filler redefines display-with-decimals.
    05  filler PIC x(9).
    05  part-less-than-100 PIC 9(6).
        88 a-round-number-to-100-already VALUE ZERO.


Code:

MOVE comp-3-with-decimals TO display-no-decimals
IF NOT a-round-number-to-100-already
    MOVE ZERO TO part-less-than-100
    ADD 100 TO display-with-decimals
    MOVE display-with-decimals TO comp-3-with-decimals
END-IF


Quote:
It would also be possible by redefining the comp-3.

Might be another way even simpler... checking....


The simpler way I was thinking of isn't worth it, because you are not "rounding" in the way Cobol does it.

To redefine the comp-3 you'd need an odd-number of decimal places, so that everything which needs to be tested/zeroed is within byte boundaries. It is a more obscure solution, so you'd only want it for the necessity of hotter-than-hot performance as there would be too much danger of confusing subsequent readers of your program (including you after a period of time).

EDIT: Not actually as obscure as I was thinking of initially.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Tue Mar 06, 2012 8:42 pm
Reply with quote

Rats. The 10 minutes you have to do any editing in, is definitely from the time of the original post, not from the time of the last edit :-)

Because you need an odd-number of decimal places, and because that would change the outcome of the original computation (to three, or five, places) as far as this odd rounding-up is concerned, I am again coming out against redefining the comp-3 as you'd need another comp-3 with five decimal places, a move to that, the stuff, then move back again. Do the MOVEs with the DISPLAY field, much less worry about confusing others (or yourself if you have a tendency to forget your own code after a while).
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Tue Mar 06, 2012 11:06 pm
Reply with quote

whether display or comp-3 data elements are used,
the 'algorithm' is the same.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Tue Mar 06, 2012 11:42 pm
Reply with quote

For the fancy multiply/divide, yes, display, comp-3, the same (it'll all get done in comp-3 by the compiler).

For the redefines, the comp-3 matters.

Code:
01 this-one comp-3 pic s9(11)v9(4).

01 that-one comp-3 pic s9(12)v9(5).

If both contain 101 and then 100

Code:

X'00 00 00 00 10 10 00 0C'
X'00 00 00 00  01 01 00 00 0C'
X'00 00 00 00 10 00 00 0C'
X'00 00 00 00  01 00 00 00 0C'

By redefining the second as filler pic x(5) and a-thing comp-3 pic s9(7), I can do the test for zero. With the first, I can't, as the "tens" is in the next byte to the left of the units,

Thus making the code for the redefines of the comp-3 obscure and error-prone (only works with odd-number of decimals). Plus you need to do a MOVE to the field, else you run the risk of getting different answers with one more/less digit of precision (like .00004 would be .0000 in the original calculations.

Defining a display field and moving to/from that is unproblematic, as long as a redefines can be coded correctly..
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Wed Mar 07, 2012 12:00 am
Reply with quote

bill,
yes, you are correct
and repeating yourself
Back to top
View user's profile Send private message
chowdhrykapildev

New User


Joined: 05 Aug 2009
Posts: 44
Location: Hyderabad

PostPosted: Mon Mar 12, 2012 7:34 pm
Reply with quote

Thanks to one & all for your inputs. I used Robert's code and its working. :-)
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun Mar 18, 2012 7:17 am
Reply with quote

Just for fun :-)
Code:

       ID DIVISION.
       PROGRAM-ID. STUBUP1.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  W-WHEN-COMPILED                      PIC X(8)BX(8).
       01  WS-FULLDATA   PIC S9(11)V9(04) COMP-3.
       01  WS-INTDATA    PIC S9(11) COMP-3.
       01  WS-REMAINDER  PIC S9(3)V9(4) COMP-3.
       01  DISPLAY-WITH-DECIMALS PIC S9(11)V9(4).
       01  FILLER REDEFINES DISPLAY-WITH-DECIMALS.
           05  FILLER PIC X(9).
           05  PART-LESS-THAN-100 PIC S9(6).
               88 A-ROUND-NUMBER-TO-100-ALREADY VALUE ZERO.
       LINKAGE SECTION.
       01  L-PARM-DATA.
           05  L-PARM-LENGTH COMP PIC S9(4).
           05  L-PARM-IND PIC X.
           05  L-PARM-REPEAT PIC 9(8).
       PROCEDURE DIVISION USING L-PARM-DATA.
                                                                   
           MOVE WHEN-COMPILED           TO W-WHEN-COMPILED
           DISPLAY "STUBUP1 " W-WHEN-COMPILED
                                                                   
           MOVE 13333.0033              TO  WS-FULLDATA.
           IF L-PARM-IND EQUAL TO "A"
               PERFORM                  A-DUMMY
                                          L-PARM-REPEAT TIMES
               DISPLAY WS-FULLDATA
           ELSE
               PERFORM                  B-DUMMY
                                          L-PARM-REPEAT TIMES
               DISPLAY WS-FULLDATA
           END-IF
           GOBACK
           .
       A-DUMMY.
                                                                   
           DIVIDE WS-FULLDATA BY 100
               GIVING WS-INTDATA
               REMAINDER WS-REMAINDER
           IF  WS-REMAINDER > ZERO
               ADD 1                  TO  WS-INTDATA
           END-IF.
           COMPUTE WS-FULLDATA = WS-INTDATA * 100
           .
       B-DUMMY.
           MOVE WS-FULLDATA             TO DISPLAY-WITH-DECIMALS
           IF NOT A-ROUND-NUMBER-TO-100-ALREADY
               MOVE ZERO                TO PART-LESS-THAN-100
               ADD +100                 TO DISPLAY-WITH-DECIMALS
                 GIVING                 WS-FULLDATA
           END-IF
           .



Code:
//RUNITA EXEC PGM=STUBUP1,TIME=(,10),PARM=A01000000
//STEPLIB DD DSN=your load,DISP=SHR
//SYSLST DD  SYSOUT=*
//SYSOUT DD  SYSOUT=*
//RUNITB EXEC PGM=STUBUP1,TIME=(,10),PARM=B01000000
//STEPLIB DD DSN=your load,DISP=SHR
//SYSLST DD  SYSOUT=*
//SYSOUT DD  SYSOUT=*


I've made a tweak to my code (and made it compile) and changed the fields in the other cide to conp-3 from the for-demonstration-only usage. Chopped the remainder down a bit.

It is the same algorithm, just different implementations.

If doing multiplication/division by nice round numbers, always faster to do it with the data.
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 Extracting Variable decimal numbers f... DFSORT/ICETOOL 17
No new posts Pulling a fixed number of records fro... DB2 2
No new posts Substring number between 2 characters... DFSORT/ICETOOL 2
No new posts Generate random number from range of ... COBOL Programming 3
No new posts Increase the number of columns in the... IBM Tools 3
Search our Forums:

Back to Top