I would like to add a kind of ripple to an array of known values of type double. I point that out because Random.Next / Random.NextDouble() behave different.
Below is my solution.
Basically, it "jitters" each value by some specified percentage, and then checks the difference between the original total and the "jittered" total. In order to make the final total match the original total, it adds a flat amount to each "jittered" value.
I feel like this is not a great solution from a mathematical perspective, because I think that adding the flat amount to each value will probably distort the true percentage of abberation for each value. There is probably a more mathematically correct way to apply the remainder across the set of values in such a way as to preserve the intended percentage of abberation, but I imagine that doing so would require several passes, whereas this solution completes in a set number of passes.
// prepare data
double[] values = new double[20];
for (int i = 0; i < values.Length; i++)
{
values[i] = 40.0;
}
// get the original total
double originalTotal = 0.0;
for (int i = 0; i < values.Length; i++)
{
originalTotal += values[i];
}
// specify an abberation percentage
double x = 0.05;
// jitter each value +/- the abberation percentage
// also capture the total of the jittered values
Random rng = new Random();
double intermediateTotal = 0.0;
for (int i = 0; i < values.Length; i++)
{
values[i] += values[i] * (rng.NextDouble() - 0.5) * (2.0 * x);
intermediateTotal += values[i];
}
// calculate the difference between the original total and the current total
double remainder = originalTotal - intermediateTotal;
// add a flat amount to each value to make the totals match
double offset = remainder / values.Length;
for (int i = 0; i < values.Length; i++)
{
values[i] += offset;
}
// calculate the final total to verify that it matches the original total
double finalTotal = 0.0;
for (int i = 0; i < values.Length; i++)
{
finalTotal += values[i];
}