Saturday, 7 January 2017

C# vs COBOL decimal rounding



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!


Answer



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".


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...