Naresh
Naresh

Reputation: 2673

How to divide a number into multiple parts so that the resulting sum is equal to the input?

I am trying to divide a number into multiple parts so the sum of the part are equal to the input number.

If I have 3.99 and if I need to divide into two parts, the expected output is 2 and 1.99 (2+1.99=3.99)

And if I need to divide 3.99 into 3 parts, the expected output is 1.3, 1.3 and 1.39 (1.3+1.3+1.39=3.99)

I was able to output 2.99 and 1 for the first example and I was able to get 1.99, 1 and 1 for the second example. However, in both the cases results are very far from the expected output.

I need to split postal charges into separate line items. The result could be equally divided or unequally divided while making sure that the sum of the different parts is equal to the input number.

Here are some other examples:

3.99 divided in 3 parts: 1.33, 1.33, 1.33
3.98 divided in 3 parts: 1.33, 1.33, 1.32
3.97 divided in 3 parts: 1.32, 1.32, 1.33
3.96 divided in 3 parts: 1.32, 1.32, 1.32
3.95 divided in 3 parts: 1.32, 1.32, 1.31

Upvotes: 11

Views: 14105

Answers (3)

Priya
Priya

Reputation: 367

I had a requirement in which a number for ex: 29 is divided into a constant arrays and the remainder has to be appended at the last.

29= 9,9,9,3. for this my code is.

       List<int> split(int num,int splitBy)
           {

               List<int> r = new List<int>();
               int v = Convert.ToInt32(num / splitBy);
               r.AddRange(Enumerable.Repeat(splitBy, v).ToArray());
               var remaining = num % splitBy;
               if (remaining != 0)
                   r.Add(remaining);
               return r;

           }

Happy coding!!!

Upvotes: 3

Mridul
Mridul

Reputation: 757

In case someone is intending to split in rounded numbers using an extension method, It ca be done so by doing the below. Eg. split 25 into 4 would give a result like 6,6,6,7. Thanks @ Jon B

 public static IEnumerable<int> PartitionMeInto(this int value, int count)
    {
        if (count <= 0) throw new ArgumentException("count must be greater than zero.", "count");
        var result = new int[count];

        int runningTotal = 0;
        for (int i = 0; i < count; i++)
        {
            var remainder = value - runningTotal;
            var share = remainder > 0 ? remainder / (count - i) : 0;
            result[i] = share;
            runningTotal += share;
        }

        if (runningTotal < value) result[count - 1] += value - runningTotal;

        return result;
    }

Usage

        int value = 25;

        var result = value.PartitionMeInto(4);

Upvotes: 4

user27414
user27414

Reputation:

I tested with your supplied values. May need some tweaking:

static IEnumerable<decimal> SplitValue2(decimal value, int count)
{
    if (count <= 0) throw new ArgumentException("count must be greater than zero.", "count");
    var result = new decimal[count];

    decimal runningTotal = 0M;
    for (int i = 0; i < count; i++)
    {
        var remainder = value - runningTotal;
        var share = remainder > 0M ? Math.Max(Math.Round(remainder / ((decimal)(count - i)), 2), .01M) : 0M;
        result[i] = share;
        runningTotal += share;
    }

    if (runningTotal < value) result[count - 1] += value - runningTotal;

    return result;
}

This assumes you pass in a value with 2 decimal precision. If you pass in 3.999, you're not going to get correct results.

Upvotes: 6

Related Questions