How to convert c++ code to cobol correctly - cobol

I have written code to get the number that appears the most in an array. The main function will make a call to readData which will read data into the array that I passed to the readData subroutine. After the readData subroutine has executed, i use the mode function to find the number that appears most in an array.
Example array: |1|2|2|1|1|
Output generated: 1
My c++ code is as follows:
#include <iostream>
using namespace std;
void mode(int array[]){
int max = 0, num;
int count;
for(int i=0; i<5; ++i){
count = 0;
for(int j=0; j<5; ++j){
if(array[i] == array[j]){
++count;
}
if(max < count){
max = count;
num = array[i];
}
}
}
cout << num << endl;
}
void arrayData(int array[]){
for(int i=0; i<5; i++){
cin >> array[i];
}
mode(array);
}
int main()
{
int array[5];
arrayData(array);
return 0;
}
I would like to convert the above c++ code to cobol, I am using gnuCobol. The code i have generated so far is bellow.
IDENTIFICATION DIVISION.
PROGRAM-ID. Main.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 array.
05 val PIC X(1) OCCURS 5 TIMES.
PROCEDURE DIVISION.
CALL 'READDATA' USING array.
STOP RUN.
*> readData: fills the array with user diffined digits
IDENTIFICATION DIVISION.
PROGRAM-ID. READDATA.
WORKING-STORAGE SECTION. ***> error appears here**
01 array.
05 val PIC X(1) OCCURS 5 TIMES.
PROCEDURE DIVISION.
PERFORM VARYING I FROM 1 BY 1
UNTIL I > 5
SET I TO 1
ACCEPT array(I) FROM SYSIN.
SET I UP BY 1
END-PERFORM.
CALL 'MODE' USING array.
EXIT PROGRAM.
*> mode: gets the number that appears most in the array
IDENTIFICATION DIVISION.
PROGRAM-ID. MODE.
WORKING-STORAGE SECTION.
01 array.
05 val PIC X(1) OCCURS 5 TIMES.
01 maxv PIC(1) VALUE 0.
01 counter PIC(1).
01 num PIC(1).
PROCEDURE DIVISION.
PERFORM VARYING I FROM 1 BY 1
UNTIL I > 5
MOVE 0 TO counter
PERFORM VARYING J FROM 1 BY 1
UNTIL J > 5
IF array(I) = array(I) THEN
SET counter UP BY 1
END-IF
IF maxv < counter THEN
MOVE counter TO maxv
MOVE array(I) TO num
END-IF
SET J UP BY 1
END-PERFORM.
SET I UP BY 1
END-PERFORM.
DISPLAY "Mode: "num.
EXIT PROGRAM.
I am getting the following error:
Error: syntax error, unexpected "WORKING-STORAGE", expecting "END PROGRAM" or "PROGRAM-ID"

There were several issues with the code. The reported error appears to have been the absence of an END PROGRAM statement to separate the first program from the second.
Other errors include:
Using SET statements unnecessarily
Passing the array without a LINKAGE SECTION or USING phrase
Missing DATA DIVISION statements
Missing data items
Improper subscripting
Including a "separator period" before a scope terminator
Invalid PICTURE clauses
These issues are shown in comments in the following code. Compare the original code with the modified code.
Modified code:
IDENTIFICATION DIVISION.
PROGRAM-ID. Main.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 array.
05 val PIC X(1) OCCURS 5 TIMES.
PROCEDURE DIVISION.
CALL 'READDATA' USING array.
STOP RUN.
END PROGRAM MAIN. *> ADDED
*> readData: fills the array with user diffined digits
IDENTIFICATION DIVISION.
PROGRAM-ID. READDATA.
DATA DIVISION. *> ADDED
WORKING-STORAGE SECTION. *> error appears here**
01 I PIC 9.
LINKAGE SECTION. *> ADDED
01 array.
05 val PIC X(1) OCCURS 5 TIMES.
PROCEDURE DIVISION USING ARRAY. *> MODIFIED
PERFORM VARYING I FROM 1 BY 1
UNTIL I > 5
*> SET I TO 1 *> REMOVED
ACCEPT VAL (I) FROM SYSIN *> MODIFIED
*> SET I UP BY 1 *> REMOVED
END-PERFORM.
CALL 'MO-DE' USING array.
EXIT PROGRAM.
END PROGRAM READDATA. *> ADDED
*> mode: gets the number that appears most in the array
IDENTIFICATION DIVISION.
PROGRAM-ID. MO-DE. *> 'MODE' IS A RESERVED WORD
DATA DIVISION. *> ADDED
WORKING-STORAGE SECTION.
01 maxv PIC 9 VALUE 0. *> MODIFIED
01 counter PIC 9. *> MODIFIED
01 num PIC 9. *> MODIFIED
01 I PIC 9. *> ADDED
01 J PIC 9. *> ADDED
LINKAGE SECTION. *> ADDED
01 array.
05 val PIC X(1) OCCURS 5 TIMES.
PROCEDURE DIVISION USING ARRAY. *> MODIFIED
PERFORM VARYING I FROM 1 BY 1
UNTIL I > 5
MOVE 0 TO counter
PERFORM VARYING J FROM 1 BY 1
UNTIL J > 5
IF VAL (I) = VAL (J) THEN *> MODIFIED
ADD 1 TO COUNTER *> MODIFIED
END-IF
IF maxv < counter THEN
MOVE counter TO maxv
MOVE VAL (I) TO num
END-IF
*> SET J UP BY 1 *> REMOVED
END-PERFORM *> MODIFIED
*> SET I UP BY 1 *> REMOVED
END-PERFORM.
DISPLAY "Mode: "num.
EXIT PROGRAM.
END PROGRAM MO-DE. *> ADDED
Input:
1
5
5
2
3
Output:
Mode: 5

Related

Ada - how to explicitly pack a bit-field record type?

Please consider the following experimental Ada program which attempts to create a 32-bit record with well defined bit fields, create one and output it to a file stream...
with System;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Streams.Stream_Io; use Ada.Streams.Stream_Io;
procedure Main is
type Bit is mod (2 ** 1);
type Opcode_Number is mod (2 ** 4);
type Condition_Number is mod (2 ** 4);
type Operand is mod (2 ** 9);
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-- ADA 2012 language reference 'full_type_declaration'
-- (page 758, margin number 8/3) for RAM_Register
pragma Atomic (RAM_Register);
-- 3 2 1 0
-- 10987654321098765432109876543210
-- OOOOzcriCONDrrDDDDDDDDDsssssssss
X : RAM_Register := (2#1000#,
2#1#,
2#1#,
2#1#,
2#1#,
2#1000#,
2#1#,
2#1#,
2#100000001#,
2#100000001#);
The_File : Ada.Streams.Stream_IO.File_Type;
The_Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
begin
Open (The_File, Out_File, "test.dat");
exception
when others =>
Create (The_File, Out_File, "test.dat");
end;
The_Stream := Stream (The_File);
RAM_Register'Write (The_Stream, X);
Close (The_File);
end Main;
I used the info here: https://rosettacode.org/wiki/Object_serialization#Ada and here: https://en.wikibooks.org/wiki/Ada_Programming/Attributes/%27Bit_Order (the very last example) to create the above.
Running the code and examining the output with xxd -g1 test.dat gives the following 12 bytes of output...
00000000: 08 01 01 01 01 08 01 01 01 01 01 01 ............
QUESTION:
How can this 32 bit record be written to, or read from, a stream as 32 bits, observing all bitfield positions? Imagine I was communicating with a microcontroller on an RS-232 port, each bit will be required to be exactly in the right place at the right time. The syntax for RAM_Register use record... seems to have had no effect on how 'Write arranges its output.
If I do provide my own 'Read and 'Write implementations, doesn't that directly contradict the 'for RAM_Register use record...` code?
You probably will have to convert the instance to an unsigned integer (via an unchecked conversion) and then write the unsigned integer to the stream. The default implementation of Write ignores the representation clause (see also RM 13 9/3):
For composite types, the Write or Read attribute for each component is called in canonical order, [...]
So, add
with Interfaces; use Interfaces;
with Ada.Unchecked_Conversion;
and define RAM_Register as
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record with Atomic;
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register);
for RAM_Register'Write use Write;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-----------
-- Write --
-----------
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register)
is
function To_Unsigned_32 is
new Ada.Unchecked_Conversion (RAM_Register, Unsigned_32);
U32 : Unsigned_32 := To_Unsigned_32 (Item);
begin
Unsigned_32'Write (Stream, U32);
end Write;
This yields
$ xxd -g1 test.dat
00000000: 01 03 8e 8f ....
Note: the bitorder may have been reversed as I had to comment the aspect specification for RAM_Register'Bit_Order use System.High_Order_First;

How does _mm_mul_ps() add two __m128?

I´m doing a program that takes two matrix 4x4 and multiply them using Intrinsics.
What I understand until now:
MMX/SSE instructions set allow you to accelerate computing. In particular it uses a 4 bytes elements vector.
__m128 represents a 16 bytes vector (4 elements of 4 bytes). Furthermore, __m128 data needs to be aligned in order to work.
Where I get lost is here:
Function _mm_mul_ps(_m128, _m128) that (as I have read) takes two vectors of 16 bytes of 4 flotats of 4 bytes. It multiply "one to one" the two vectors and returns a _m128. But, what does that _m128 vector contains exactly (the result of what)?
Function _mm_hadd_ps(_m128, _m128) adds two 16 bytes vectors (each one of 4 bytes floats). It "adds horizontaly" this way: vectorA(a1, a2, a3,a4) + vectorB(b1, b2, b3, b4) = vectorResult(a1 + a2, a3 + a4, b1 + b2, b3 + b4)
What I´m trying to do:
// Stores the result of multiply on row of A by one column of B
_declspec (align(16)) __m128 aux;
// Horizontal add
for(int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
aux= _mm_mul_ps(vectorA[i], vectorB[j]);
// Add results
aux = _mm_hadd_ps(aux, aux);
aux = _mm_hadd_ps(aux,aux);
}
}
I can´t see how the functions work (I don´t have a "mental image").

Comparing signed 64 bit number using 32 bit bitwise operations in Lua

I am using Lua on Redis and want to compare two signed 64-bit numbers, which are stored in two 8-byte/character strings.
How can I compare them using the libraries available in Redis?
http://redis.io/commands/EVAL#available-libraries
I'd like to know >/< and == checks. I think this probably involves pulling two 32-bit numbers for each 64-bit int, and doing some clever math on those, but I am not sure.
I have some code to make this less abstract. a0, a1, b0, b1 are all 32 bit numbers used to represent the msb & lsb's of two 64-bit signed int 64s:
-- ...
local comp_int64s = function (a0, a1, b0, b1)
local cmpres = 0
-- TOOD: Real comparison
return cmpres
end
local l, a0, a1, b0, b1
a0, l = bit.tobit(struct.unpack("I4", ARGV[1]))
a1, l = bit.tobit(struct.unpack("I4", ARGV[1], 5))
b0, l = bit.tobit(struct.unpack("I4", blob))
b1, l = bit.tobit(struct.unpack("I4", blob, 5))
print("Cmp result", comp_int64s(a0, a1, b0, b1))
EDIT: Added code
I came up with a method that looks like it's working. It's a little ugly though.
The first step is to compare top 32 bits as 2 compliment #’s
MSB sign bit stays, so numbers keep correct relations
-1 —> -1
0 —> 0
9223372036854775807 = 0x7fff ffff ffff ffff -> 0x7ffff ffff = 2147483647
So returning the result from the MSB's works unless they are equal, then the LSB's need to get checked.
I have a few cases to establish the some patterns:
-1 = 0xffff ffff ffff ffff
-2 = 0xffff ffff ffff fffe
32 bit is:
-1 -> 0xffff ffff = -1
-2 -> 0xffff fffe = -2
-1 > -2 would be like -1 > -2 : GOOD
And
8589934591 = 0x0000 0001 ffff ffff
8589934590 = 0x0000 0001 ffff fffe
32 bit is:
8589934591 -> ffff ffff = -1
8589934590 -> ffff fffe = -2
8589934591 > 8589934590 would be -1 > -2 : GOOD
The sign bit on MSB’s doesn’t matter b/c negative numbers have the same relationship between themselves as positive numbers. e.g regardless of sign bit, lsb values of 0xff > 0xfe, always.
What about if the MSB on the lower 32 bits is different?
0xff7f ffff 7fff ffff = -36,028,799,166,447,617
0xff7f ffff ffff ffff = -36,028,797,018,963,969
32 bit is:
-..799.. -> 0x7fff ffff = 2147483647
-..797.. -> 0xffff ffff = -1
-..799.. < -..797.. would be 2147483647 < -1 : BAD!
So we need to ignore the sign bit on the lower 32 bits. And since the relationships are the same for the LSBs regardless of sign, just using
the lowest 32 bits unsigned works for all cases.
This means I want signed for the MSB's and unsigned for the LSBs - so chaging I4 to i4 for the LSBs. Also making big endian official and using '>' on the struct.unpack calls:
-- ...
local comp_int64s = function (as0, au1, bs0, bu1)
if as0 > bs0 then
return 1
elseif as0 < bs0 then
return -1
else
-- msb's equal comparing lsbs - these are unsigned
if au1 > bu1 then
return 1
elseif au1 < bu1 then
return -1
else
return 0
end
end
end
local l, as0, au1, bs0, bu1
as0, l = bit.tobit(struct.unpack(">i4", ARGV[1]))
au1, l = bit.tobit(struct.unpack(">I4", ARGV[1], 5))
bs0, l = bit.tobit(struct.unpack(">i4", blob))
bu1, l = bit.tobit(struct.unpack(">I4", blob, 5))
print("Cmp result", comp_int64s(as0, au1, bs0, bu1))
Comparing is a simple string compare s1 == s2.
Greater than is when not s1 == s2 and i1 < i2.
Less than is the real work. string.byte allows to get single bytes as unsigned char. In case of unsigned integer, you would just have to check bytes-downwards: b1==b2 -> check next byte; through all bytes -> false (equal); b1>b2 -> false (greater than); b1<b2 -> true. Signed requires more steps: first check the sign bit (uppermost byte >127). If sign 1 is set but not sign 2, integer 1 is negative but not integer 2 -> true. The opposite would obviously result in false. When both signs are equal, you can do the unsigned processing.
When you can pack more bytes to an integer, it's fine too, but you have to adjust the sign bit check. When you have LuaJIT, you can use the ffi library to cast your string into a byte array into an int64.

SET A, 0x1E vs SET A, 0x1F

This is my first attempt at dpcu, I'm checking machine code generated by dpcu-16 assembly
I am using this emulator : http://dcpu.ru/
I am trying to compare code generated by
SET A, 0x1E
SET A, 0x1F
code generated is as follow :
fc01
7c01 001f
I don't get why operand size changes between those two values
That emulator appears to be using the next version of the DCPU-16 spec, which specifies that the same-word literal value for a permits values from 0xFFFF (-1) to 0x1E (30). This means that to get any literal value outside this range the assembler has to use the next-word literal syntax, which makes the operand one byte bigger.
0x1F (dec:31) is no longer a short literal (values -1 to 30), so it has to be read as a "next word" argument.
The opcodes are thus:
SET A, 0x1E
SET = 00001
A = 00000
1E = 111111
op = 1111110000000001 = fc01
SET A, 0x1F
SET = 00001
A = 00000
NW = 011111
op = 0111110000000001 = 7c01 + 001f

compute rounded in cobol

I am confused with the rounded in the compute function in cobol.
Declaration:
VAR-A PIC S9(9)V99 COMP-3.
VAR-B PIC S9(9)V9(6) COMP-3.
Procedure.
MOVE +12.08 TO VAR-A.
MOVE +6.181657 TO VAR-B.
COMPUTE VAR-A ROUNDED = VAR-A + VAR-B.
Will the result of VAR-A be 18.27 or 18.26? What would cobol do upon computing?
Would it round VAR-B first to the decimal places specified in VAR-A or will cobol add the 2 variables then round them up to the decimal places specified in VAR-A?
Any help will be appreciated.
#NealB,
How about this example:
DECLARATION:
01 VAR-ARRAY OCCURS 22 TIMES.
03 VAR-A PIC S9(9)V9(6) COMP-3.
01 VAR-B PIC S9(9)V99 COMP-3.
Supposing VAR-A is an array, and the following are its values:
VAR-A(01) = 123.164612
VAR-A(02) = 12.07865
VAR-A(03) = 6.181657
VAR-A(04) = 1.744353
VAR-A(05) = 6.118182
VAR-A(06) = 1.744353
VAR-A(07) = 6.158715
VAR-A(08) = 1.744353
VAR-A(09) = 6.194759
VAR-A(10) = 1.744353
VAR-A(11) = 3.037896
VAR-A(12) = 1.743852
VAR-A(13) = 6.14653
VAR-A(14) = 1.744353
VAR-A(15) = 0.000377
VAR-A(16) = 1.743852
VAR-A(17) = 6.144363
VAR-A(18) = 1.743852
VAR-A(19) = 0.007649
VAR-A(20) = 1.744353
VAR-A(21) = 0.000377
VAR-A(22) = 1.744353
VAR-B's value is:
VAR-B = 405.25
PROCEDURE:
PERFORM VAR-IDX FROM 1 BY 1 UNTIL VAR-IDX > 22
COMPUTE VAR-B ROUNDED = VAR-B + VAR-A(VAR-IDX)
END-PERFORM.
Why do I get 597.87 for VAR-B as a result after the computation?
I believe the default COBOL rounding behaviour is: Nearest away from zero.
COMPUTE VAR-A ROUNDED = VAR-A + VAR-B
should result in VAR-A containing 18.26
Rounding occurs after the expression has been evaluated. A more interesting example might be:
01 VAR-A PIC S9(9)V99 COMP-3.
01 VAR-B PIC S9(9)V9(6) COMP-3.
01 VAR-C PIC S9(9)V9(6) COMP-3.
MOVE +12.08 TO VAR-A.
MOVE +06.182000 TO VAR-B.
MOVE +00.004000 TO VAR-C.
COMPUTE VAR-A ROUNDED = VAR-A + VAR-B + VAR-C.
The result is 18.27. Rounding VAR-B and VAR-C to 2 decimal places before doing the addition would have yielded 18.26 because VAR-B rounds to 6.18 and VAR-C rounds to 0.00. The result is actually 18.27 so the rounding occurs after evaluation of the expression.
Reply to edited question
Not pretty output, but this is how my calculation goes using IBM Enterprise COBOL for z/OS
VAR-IDX = 01 VAR-B = +405.25 VAR-A = +123.164612 VAR-B + VAR-A = +528.41
VAR-IDX = 02 VAR-B = +528.41 VAR-A = +012.078650 VAR-B + VAR-A = +540.49
VAR-IDX = 03 VAR-B = +540.49 VAR-A = +006.181657 VAR-B + VAR-A = +546.67
VAR-IDX = 04 VAR-B = +546.67 VAR-A = +001.744353 VAR-B + VAR-A = +548.41
VAR-IDX = 05 VAR-B = +548.41 VAR-A = +006.118182 VAR-B + VAR-A = +554.53
VAR-IDX = 06 VAR-B = +554.53 VAR-A = +001.744353 VAR-B + VAR-A = +556.27
VAR-IDX = 07 VAR-B = +556.27 VAR-A = +006.158715 VAR-B + VAR-A = +562.43
VAR-IDX = 08 VAR-B = +562.43 VAR-A = +001.744353 VAR-B + VAR-A = +564.17
VAR-IDX = 09 VAR-B = +564.17 VAR-A = +006.194759 VAR-B + VAR-A = +570.36
VAR-IDX = 10 VAR-B = +570.36 VAR-A = +001.744353 VAR-B + VAR-A = +572.10
VAR-IDX = 11 VAR-B = +572.10 VAR-A = +003.037896 VAR-B + VAR-A = +575.14
VAR-IDX = 12 VAR-B = +575.14 VAR-A = +001.743852 VAR-B + VAR-A = +576.88
VAR-IDX = 13 VAR-B = +576.88 VAR-A = +006.146530 VAR-B + VAR-A = +583.03
VAR-IDX = 14 VAR-B = +583.03 VAR-A = +001.744353 VAR-B + VAR-A = +584.77
VAR-IDX = 15 VAR-B = +584.77 VAR-A = +000.000377 VAR-B + VAR-A = +584.77
VAR-IDX = 16 VAR-B = +584.77 VAR-A = +001.743852 VAR-B + VAR-A = +586.51
VAR-IDX = 17 VAR-B = +586.51 VAR-A = +006.144363 VAR-B + VAR-A = +592.65
VAR-IDX = 18 VAR-B = +592.65 VAR-A = +001.743852 VAR-B + VAR-A = +594.39
VAR-IDX = 19 VAR-B = +594.39 VAR-A = +000.007649 VAR-B + VAR-A = +594.40
VAR-IDX = 20 VAR-B = +594.40 VAR-A = +001.744353 VAR-B + VAR-A = +596.14
VAR-IDX = 21 VAR-B = +596.14 VAR-A = +000.000377 VAR-B + VAR-A = +596.14
VAR-IDX = 22 VAR-B = +596.14 VAR-A = +001.744353 VAR-B + VAR-A = +597.88
FINAL RESULT = +597.88
It depends on the intermediate rounding and the final rounding set.
see this for more info :
D.13a Rounding
COBOL provides the capability of specifying rounding in arithmetic statements and expressions at various points in the evaluation process and as values are prepared for storing in receiving data items.
There are eight different forms of rounding supported by this standard:
• AWAY-FROM-ZERO: Rounding is to the nearest value of larger magnitude.
• NEAREST-AWAY-FROM-ZERO: Rounding is to the nearest value. If two values are equally near, the value with the larger magnitude is selected. This mode has historically been associated with the ROUNDED clause in previous versions of standard COBOL.
• NEAREST-EVEN: Rounding is to the nearest value. If two values are equally near, the value whose rightmost digit is even is selected. This mode is sometimes called “Banker’s rounding”.
• NEAREST-TOWARD-ZERO: Rounding is to the nearest value. If two values are equally near, the value with the smaller magnitude is selected.
• PROHIBITED: Since the value cannot be represented exactly in the desired format, the EC-SIZE-TRUNCATION condition is set to exist and the results of the operation are undefined.
• TOWARD-GREATER: Rounding is toward the nearest value whose algebraic value is larger.
• TOWARD-LESSER: Rounding is toward the nearest value whose algebraic value is smaller.
• TRUNCATION: Rounding is to the nearest value whose magnitude is smaller. This mode has historically been associated with the absence of the ROUNDED clause as well as for the formation of intermediate results in the prior COBOL standard.
The programmer may specify how individual intermediate values are rounded when they are stored into receiving data items through the ROUNDED clause; may select a default mode of rounding to be used when the ROUNDED clause appears with no further qualification on a receiving data item through the DEFAULT ROUNDED MODE clause of the OPTIONS paragraph of the IDENTIFICATION DIVISION; and may specify how arithmetic operations and conversions to and from intermediate forms are rounded through the INTERMEDIATE ROUNDING clause.
D.13a.1 Intermediate rounding
Intermediate rounding applies when data items are retrieved for inclusion in an arithmetic operation or arithmetic expression, and during the execution of arithmetic operators to produce an intermediate result.
In the previous standard, for multiplication and division in Standard Arithmetic, the default mode of rounding for inexact results was truncation to 32 significant digits. This default is unchanged in this standard, and is also the default for Standard-Binary and Standard-Decimal arithmetic.
When the intermediate value can be represented exactly in the appropriate intermediate format, the exact value is used.
In the event the value cannot be exactly represented, the user may also now specify other modes of rounding for arithmetic operations and for the conversions to and from intermediate forms used in the arithmetic operations through the optional INTERMEDIATE ROUNDING clause of the OPTIONS paragraph of the IDENTIFICATION DIVISION.
Specifically, the following options are available:
• INTERMEDIATE ROUNDING IS NEAREST-AWAY-FROM-ZERO
• INTERMEDIATE ROUNDING IS NEAREST-EVEN
• INTERMEDIATE ROUNDING IS PROHIBITED
• INTERMEDIATE ROUNDING IS TRUNCATION
for which the subclause descriptions are found in D.13a, Rounding.
If the INTERMEDIATE ROUNDING clause is not specified, INTERMEDIATE ROUNDING IS TRUNCATION is presumed. This is unchanged from previous standards.
D.13a.2 Final rounding (the ROUNDED clause)
Final rounding applies to the formation of the final result of the expression or statement, at the completion of evaluation of the statement or expression, immediately before the result is placed in the destination. This form of rounding is that which is associated with the ROUNDED clause.
In previous COBOL standards, only two methods of “final” rounding were provided: rounding toward the smaller magnitude (truncation, signaled by the absence of the ROUNDED clause); and rounding to the nearest values, and if two values were equally near, choose the value with the larger magnitude (signaled by the presence of the ROUNDED clause).
The ROUNDED clause has been enhanced to allow explicit selection of any of eight modes of rounding (including the two previously available):
• ROUNDED MODE IS AWAY-FROM-ZERO
• ROUNDED MODE IS NEAREST-AWAY-FROM-ZERO
• ROUNDED MODE IS NEAREST-EVEN
• ROUNDED MODE IS NEAREST-TOWARD-ZERO
• ROUNDED MODE IS PROHIBITED
• ROUNDED-MODE IS TOWARD-GREATER
• ROUNDED MODE IS TOWARD-LESSER
• ROUNDED MODE IS TRUNCATION
If the ROUNDED clause is not present for a given result, the rules for ROUNDED MODE IS TRUNCATION apply.
The optional DEFAULT ROUNDED MODE clause in the OPTIONS paragraph of the IDENTIFICATION DIVISION is provided to allow the user to specify the mode of rounding to any operation for which the ROUNDED clause appears without the MODE IS subclause.
The DEFAULT ROUNDED MODE clause may take any of these forms:
• DEFAULT ROUNDED MODE IS AWAY-FROM-ZERO
• DEFAULT ROUNDED MODE IS NEAREST-AWAY-FROM-ZERO
• DEFAULT ROUNDED MODE IS NEAREST-EVEN
• DEFAULT ROUNDED MODE IS NEAREST-TOWARD-ZERO
• DEFAULT ROUNDED MODE IS PROHIBITED
• DEFAULT ROUNDED MODE IS TOWARD-GREATER
• DEFAULT ROUNDED MODE IS TOWARD-LESSER
• DEFAULT ROUNDED MODE IS TRUNCATION
for which the subclauses of the DEFAULT ROUNDED MODE is clause are described in D.13a, Rounding.
If the DEFAULT ROUNDED MODE clause does not appear in the program, the effect of the ROUNDED clause without the MODE IS subclause is as if ROUNDED MODE IS NEAREST AWAY FROM ZERO had been specified. This provides the same functionality available in prior COBOL standards.
If the DEFAULT ROUNDED MODE clause appears, ROUNDED clauses without the MODE IS subclause are treated as if they had been specified with the rounding mode specified in the DEFAULT ROUNDED MODE clause.
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 VAR_NUM PIC 9(3)V9(02).
01 VAR_RESULT PIC 9(3).
PROCEDURE DIVISION.
MOVE 256.50 TO VAR_NUM.
COMPUTE VAR_NUM ROUNDED = VAR_NUM / 100.
MULTIPLY 100 BY VAR_NUM
MOVE VAR_NUM TO VAR_RESULT.
DISPLAY "Result : " VAR_RESULT.
STOP RUN.

Resources