Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Math Rounding Issue total > 100%

Tags:

c#

math

rounding

I have 3 values which all get rounded to no decimal places (ie 5%, 25%, 70%) except my 70% is really 70.6% so it goes to 71% which makes my total 5%, 25%, 71% = 101% which is not good, especially because i have a bar graph that if it goes over 100% width, gets really messed up.

How can i make sure that my 3 values never equal more than 100%? right now im using Math.Round(value,0) are there any switches/options i can use to keep my total of my 3 values from being over 100%?

Thanks

like image 416
tap Avatar asked Feb 09 '12 20:02

tap


1 Answers

If you don't care that the values might sum to less than 100, the simple solution is just to use Math.Floor throughout.

It gets more interesting if you want to round up/down and have the result be exactly 100. Here is one approach – round them all down, then round them up selectively biggest-fraction-first until you hit 100 again:

public static void RoundTo100Percent(IList<double> list)
{
    // get the sort order before changing any items
    IList<int> sortOrder = list.Select((n, i) => new { Key = n - Math.Truncate(n), Index = i }).OrderByDescending(ki => ki.Key).Select(ki => ki.Index).ToList();

    // round them all down to start with
    for (int i = 0; i < list.Count; i++)
    {
        list[i] = Math.Floor(list[i]);
    }

    // then round them up selectively, starting with those with the highest fractional part
    // e.g. 5.9 will round up to 6.0 before 7.8 rounds up to 8.0.
    int numberOfItemsToRoundUp = 100 - (int)list.Sum();
    foreach (int sortIndex in sortOrder.Take(numberOfItemsToRoundUp))
    {
        list[sortIndex]++;
    }
}
like image 84
Matthew Strawbridge Avatar answered Oct 04 '22 07:10

Matthew Strawbridge