View previous topic :: View next topic
|
Author |
Message |
chowdhrykapildev
New User
Joined: 05 Aug 2009 Posts: 44 Location: Hyderabad
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
prino
Senior Member
Joined: 07 Feb 2009 Posts: 1306 Location: Vilnius, Lithuania
|
|
|
|
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 |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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! |
|
Back to top |
|
|
Phrzby Phil
Senior Member
Joined: 31 Oct 2006 Posts: 1042 Location: Richmond, Virginia
|
|
|
|
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 |
|
|
chowdhrykapildev
New User
Joined: 05 Aug 2009 Posts: 44 Location: Hyderabad
|
|
|
|
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 |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
prino
Senior Member
Joined: 07 Feb 2009 Posts: 1306 Location: Vilnius, Lithuania
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
whether display or comp-3 data elements are used,
the 'algorithm' is the same. |
|
Back to top |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
bill,
yes, you are correct
and repeating yourself |
|
Back to top |
|
|
chowdhrykapildev
New User
Joined: 05 Aug 2009 Posts: 44 Location: Hyderabad
|
|
|
|
Thanks to one & all for your inputs. I used Robert's code and its working. :-) |
|
Back to top |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
|