Question

I am re-writing a COBOL program in C# that does calculations dealing with money. From some of the first calculations however, some of the decimal rounding is off (doesn't match what the COBOL program calculates).

Decimal.Round(19.87 * 2.57, 2) returns 51.07 (51.0659) in C#,

COMPUTE varA = 19.87 * 2.57 returns 51.06 in COBOL

Here COBOL rounds the number down, but in other cases it rounds up where C# rounds down. I'm at a loss.

This is one of the first calculations I have to do, so once the numbers get larger they are more and more different from the COBOL output. (I have a report I am testing numbers against.)

I have tried Math.Round, and Floor and Ceiling of both classes to get the output I should see to no avail.

UPDATE: I found what my problem was. Many of the fields used in the calculations in the COBOL program had 9 decimal places, but the result was stored in a 2 decimal place field. I was doing the calculations after truncating, instead of before and then truncating. Thanks everyone for your help! Every answer helped!

Was it helpful?

Solution

The COBOL COMPUTE that you show is simply rounding down (aka truncating). The intermediate result will be held with two decimal places and the excess value that you may expect if you used a calculator will simply disappear.

If you do not replicate that in behaviour in your new program, you will not match the figures.

It is of course possible that the COBOL program should be rounding, but you'll have to get someone to look into that.

COMPUTE varA ROUNDED = 19.87 * 2.57

Would get you 51.07, since the intermediate result will be to three decimal places, then if that third decimal place is 5-9, the second decimal place will be increased by one and only then would the result be truncated.

Be aware that the difference between COMPUTE with and without ROUNDED is important in determining your correct values. Be also aware that there are two more COBOL verbs, DIVIDE and MULTIPLY, which would naturally behave differently depending on data with and without ROUNDED. Be aware that ADD and SUBTRACT where different numbers of decimal places are involved would also...

Be also aware that the more complex a COMPUTE is, the more likely it has been coded without thought to what actual intermediate values are used. See these two, for instance: COBOL COMPUTE calculation, AS/400: Using COMPUTE function, inconsistent results with different field definition

Be also aware that the current COBOL standard is the 1985 standard, with 1989 corrections and extensions for Intrinsic Functions. The new standard is not complete, and although new elements in that are implemented in some compilers, there are not many which have implemented the definitions of different types of rounding. Without ROUNDED anyway, you will get "rounded down".

OTHER TIPS

First, I believe you need to determine the version of COBOL you are migrating from. Second, be careful of any time there is a COMPUTE ROUNDED operation as it will differ from the plain COMPUTE you have shown us.

Some helpful information on Cobol Compute here that may help you understand.

To solve your example: If you take your C# computation to three decimal places then truncate, you'll mirror the COBOL example you provided without having it rounded up. See this question for assistance on truncating numbers.

Please note that this assumes ALL your COBOL will act this way. You must verify this.

COBOL

varA seems to be defined to store 2 decimal positions. As no ROUNDED option has been specified, the multiplication result will be truncated to fit into this. This is the default behavior.

C#

You can get the same result by using Math.Truncate(x * 100m) / 100m;

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top