In wich direction would a Math.Round round if a Math.Round could round ? - Ed's Blog
in

dotnet.org.za

South African .NET Developer Portal

Ed's Blog

Object reference not set to an instance of an object

In wich direction would a Math.Round round if a Math.Round could round ?

The answer to this question is : “down”.

Let me explain : if you had to round 3.45 to 1 decimal place, most people would arive at the answer of 3.5. Micosoft, or at least Math.Round doesn't. It rounds DOWN to 3.4. the rest of the cases work the same in Math.Round as it does in the mind of an individual with average intelligence. (3.44 rounds to 3.4 and 3.46 rounds to 3.5)

The office line from the help file is :
“The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called rounding to nearest, or banker's rounding.”

So if you want the IEEE Standard for people of at least average intelligence, section 39, you can try this function I wrote to bypass this stupidity:

public static decimal Round(decimal value,int digits)
{
  if (digits < 0)
  {
    throw new ArgumentException("Must be > 0","digits");
  }

  long multiplier;
  if (digits == 0)
  {
    multiplier = 1;
  }
 
else
 
{
    multiplier = Math.Pow(10,digits);
  }

  double work = (double)value * multiplier;

  double work2 = work - Math.Floor(work);

  if (work2 >= 0.5)
  {
    return (decimal)( (Math.Floor(work) + 1) / multiplier );
  }
  else
 
{
    return (decimal)( Math.Floor(work) / multiplier );
  }
}

All jokes aside, I think they should have provided a function that rounds up as well.

Published Oct 12 2004, 02:53 PM by eduard
Filed under:

Comments

 

Ernst Kuschke said:

Cool. I just wouldn't throw the Exception if no digits are passed in - I'd rather just return the value as it is ;o)
October 12, 2004 3:18 PM
 

Ed said:

Thought I'd keep the behaviour the same as Math.Round that throws an exception. I also recon it's better to let the user know they tried to do something illegal rather than avoid the exception and let them continue oblivious to the error. Imaging if we had no division by zero or integer overflow exceptions ?
October 12, 2004 3:38 PM
 

D said:

and it gets even trickier due to the variety of implementations of the Round functions through MS products.
October 12, 2004 6:53 PM
 

Reyn said:

Math.Ceiling rounds up, I guess you meant one that can handle x decimal places ?
October 12, 2004 7:55 PM
 

Marcel said:

Just what I was looking for; except it doen't compile right off.
The long multiplier needs to be defined as a double.
Has anyone used/tested the code as it is published here? I'd like to start using it, but I'm lazy and don't want to have to test it ;-)
November 26, 2004 3:47 PM
 

Eduard said:

Marcel, I can obviously not give you a gaurentee, but we have used it on my current project for a couple of months now and we've had no trouble.
November 26, 2004 3:49 PM
 

Marcel said:

Did you change the definition for 'multiplier' to double? Or cast the result of Math.Pow(10, digits) to long?
Or didn't your compiler complain as mine does?
November 26, 2004 4:32 PM
 

fflx said:

multiplier = (long)Math.Pow(10,digits);
March 12, 2005 10:17 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Powered by Community Server (Commercial Edition), by Telligent Systems