Math.Round()

  • Thread starter Thread starter Marty
  • Start date Start date
M

Marty

Is there a function that rounds decimal numbers using the traditional 0
- 4 down and 5 - 9 up? The result from System.Math.Round(3.85) returns
3.8 instead of 3.9! Thanks.
 
Marty said:
Is there a function that rounds decimal numbers using the traditional 0
- 4 down and 5 - 9 up? The result from System.Math.Round(3.85) returns
3.8 instead of 3.9! Thanks.

Math.Round will always use Banker's Rounding (as documented).

In .NET 2.0 you can control this with the MidpointRounding enumeration,
but that isn't in 1.1.
 
Hi Marty,

When the rounded fraction is exactly between two values (ie 0.05) it is rounded towards the nearest even digit.

Since 8 is even and 9 isn't, .85 is rounded to 0.8. Likewise 0.75 is rounded to 0.8 since 7 is not even. This is due to IEEE Standard 754, section 4 (See Math.Round, Decimal.Round).

As for a method to do the traditional rounding. I believe there is one, but it eludes me for now. If you don't find any, there is always add half the rounding fraction, multiply by by the number 10^number of decimal spaces and take the integer part of that number.
 
This operates within the limits of long integers. From my memory; I did not
compile or test:

double Round(double input, int digits)
{
double fraction;
if (input >= 0)
fraction = .5;
else
fraction = -.5;
if (digits <= 0)
return (long)(input + fraction);
double multiplier = (digits * 10);
return ((long)(input * multiplier + fraction))/multiplier;
}

--
Regards,
Frank Hileman

check out VG.net: http://www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio .NET graphics editor
 
I fail to see what all the fuss is about.
Throughout the calculations you do no rounding,
because that would be asking for trouble.
You show the endresult eg. result.ToString("###.#");
and result gets nicely rounded.
 
Sometimes rounding is required as part of a middle-step in a
multi-step calculation. For example, this is often the case when the
base unit only supports a certain number of decimals (for example
money). This is also often required when an application has to
produce auditable results where the value used internally at every
intermediate step must be recorded exactly in an audit log.

Sam
 
Where you are making resullts visible, you are using
masks, and there will be no rounding problem that I am
aware of. I have written non trivial financial programs without
complicated rounding algorithms that balance to the cent.
 
Even extremely trivial applications can require rounded calculations.
Here's an example. Take a commission calculation, simply sales times
5%. Calculate the commission for a given month, and then to simulate
a year multiply that by 12. If you use masks and don't do internal
rounding you get these results:

Sales 28372.17
Commission 1418.61
Annual Commission 17023.30

So according to the application, you paid the person 17023.30 in a
year for commission. But that's wrong! Since the application
internally used 1418.6085 as the monthly commission and the person
really got paid 1418.61, the annual calculation is incorrect. The
correct results are obtained through mid-calculation rounding:

Sales 28372.17
Commission 1418.61
Annual Commission 17023.32

HTH,

Sam
 
Zach said:
Etc.

Indeed. Beyond the point I was making though.


PS my reply was incomplete:

Convert.ToDouble(3.85.ToString("######.#")) will produce 3.9 and not 3.8

Math.Round(3.85,1) will produce 3.8

Yes, it is a bit clumsy, but it does work and it is a lot
shorter than the algorithm proposed in this thread.
 
Math.Round will alternatively round up, or down, depending on the rounded
digit (try Math.Round(3.75, 1)). That is why it is useless for mathematical
operations and many financial ones. In many cases you need a consistent
round up for anything .5 or greater, when significant digits are 0. For
example, when converting from floating point coordinates to integer
coordinates, you must have a consistent rounding direction.

- Frank
 
The implementation of Math.Round() is based on IEEE Standard 754, section 4
and works as documented. Basically, you always round toward the even number.
This is refered to as Banker's Rounding.

However, a simple hack for .Net 1.1 and 1.0 is to convert to a string with
..ToString("#.#") and back again. The ToString() method uses a traditional
5/4 round.

decimal.Parse((3.65M).ToString("#.#"))

In .Net 2.0, you can simply specify how rounding should occur:
Math.Round(3.65, 1, MidpointRounding.AwayFromZero) = 3.7

Math.Round(3.65, 1, MidpointRounding.ToEven) = 3.6

BTW: The example you gave would round to 3.8 in either case. :)

Hope this helps...

Frisky
 
Back
Top