I have an annual figure, let's say for purposes of this question that the figure is 100%.
What I would like to do is have C# split the 100% figure into a curved distribution of monthly percentages based on a specific formula Y = f(X)
, that still add to 100.
This is likely primarily a math question - how could I accomplish this without manually keying in figures that add to 100?
My comment as an answer. The way to do this is to get the seasonality curve expressed over time. Let's consider a simple case, where we the curve looks like a step-ish sine-ish curve. We'll use a unit of "percentage of maximum value" to describe the curve. Seasons will be 3 months long, so winter is Dec-Feb, spring is Mar-May, etc.
The curve looks like:
Dec-Feb | Mar-May | Jun-Aug | Sep-Nov |
---|---|---|---|
20% of Max | 60% of Max | 100% of Max | 60% of Max |
If you add those all up (for 12 months), you will get 720%, or 7.2. So, the actual values you want to use are:
Dec-Feb | Mar-May | Jun-Aug | Sep-Nov |
---|---|---|---|
2.78 (i.e., 20.0/7.2) | 8.33 (60.0/7.2) | 13.89 (100.0/7.2) | 8.33 (60.0/7.2) |
Checking this to make sure it's valid:
2.78 * 3 + 8.33 * 6 + 13.89 *3 = 99.99
(or, just about 100)
Some working sample code for a C# console app using an arbitrary sinusoidal function that vaguely represents some early and late seasonality - MyFunction can be replaced with any function, including a stepwise one like above:
using System;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
int months = 12;
double[] scaleExpectations = new double[months];
for (int i = 0; i < 12; i++)
{
scaleExpectations[i] = MyFunction(i);
}
double sum = scaleExpectations.Sum(); //this is the actual Integral of the series, since it is not a real curve
double[] percents = new double[months];
for (int i = 0; i < 12; i++)
{
percents[i] = Math.Round((scaleExpectations[i] * 100) / sum, 2);
Console.WriteLine($"iteration {i} with value {percents[i]}");
if (i == 11) // remove rounding error by altering last position
{
var error = 100 - percents.Sum();
percents[i] = percents[i] + error;
}
}
Console.WriteLine(percents.Sum());
}
public static double MyFunction(double input)
{
return .4 * Math.Sin(.5 * (input - 7.5)) + .9;
}
}
}