tags:

views:

1417

answers:

6

In c# how do I evenly divide 100 into 7?

So the result would be

  1. 16
  2. 14
  3. 14
  4. 14
  5. 14
  6. 14
  7. 14

The code below is incorrect as all 7 values are set to 15 (totalling 105).

        double [] vals = new double[7];
        for (int i = 0; i < vals.Length; i++)
        {
            vals[i] = Math.Ceiling(100d / vals.Length);
        }

Is there an easy way to do this in c#?

Thanks

+6  A: 

Since this seems to be homework, here is a hint and not the full code.

You are doing Math.Ceiling and it converts 14.28 into 15.

Aamir
+1 for making me laugh
DrG
A: 

The algorithm is this

  1. Divide 100 by 7, put the result in X
  2. Get the highest even number below X and put this in Y.
  3. Multiply Y by 7 and put the answer in Z.
  4. Take Z away from 100.

The answer is then 6 lots of Y plus whatever the result of step 4 was.

This algorithm may only work for this specific instance.

I'm sure you can write that in C#

RobS
+8  A: 

To get my suggested result of 15, 15, 14, 14, 14, 14, 14:

// This doesn't try to cope with negative numbers :)
public static IEnumerable<int> DivideEvenly(int numerator, int denominator)
{
    int rem;
    int div = Math.DivRem(numerator, denominator, out rem);

    for (int i=0; i < denominator; i++)
    {
        yield return i < rem ? div+1 : div;
    }
}

Test:

foreach (int i in DivideEvenly(100, 7))
{
    Console.WriteLine(i);
}
Jon Skeet
Jon Skeet can also answer and get accepted an ambigous question. This must go the "Jon Skeet facts" question :-)
Learning
I like my linq solution better, much more spartan :)
Sam Saffron
A: 

Not sure if this is exactly what you are after, but I would think that if you use Math.ceiling you will always end up with too big a total. Math.floor would underestimate and leave you with a difference that can be added to one of your pieces as you see fit.

For example by this method you might end up with 7 lots of 14 giving you a remainder of 2. You can then either put this 2 into one of your pieces giving you the answer you suggested, or you could split it out evenly and add get two pieces of 15 (as suggested in one of the comments)

chillysapien
A: 

Not sure why you are working with doubles but wanting integer division semantics.

    double input = 100;
    const int Buckets = 7;
    double[] vals = new double[Buckets];
    for (int i = 0; i < vals.Length; i++)
    {
        vals[i] = Math.Floor(input / Buckets);
    }
    double remainder = input % Buckets;
    // give all of the remainder to the first value
    vals[0] += remainder;

example for ints with more flexibility,

    int input = 100;
    const int Buckets = 7;
    int [] vals = new int[Buckets];
    for (int i = 0; i < vals.Length; i++)
    {
        vals[i] = input / Buckets;
    }
    int remainder = input % Buckets;
    // give all of the remainder to the first value
    vals[0] += remainder;

    // If instead  you wanted to distribute the remainder evenly, 
    // priority to first
    for (int r = 0; r < remainder;r++)
    {
        vals[r % Buckets] += 1;
    }

It is worth pointing out that the double example may not be numerically stable in that certain input values and bucket sizes could result in leaking fractional values.

ShuggyCoUk
+6  A: 

Here you go:

Func<int, int, IEnumerable<int>> f = (a, b) => 
 Enumerable.Range(0,a/b).Select((n) => a / b + ((a % b) <= n ? 0 : 1))

Good luck explaining it in class though :)

Sam Saffron