This is probably a naïve approach but you could split the random generation into multiple steps.
For example, say you want 70% of the ages to be between 20 and 70, you could introduce an additional random check:
if (random.NextDouble() >= 0.3)
{
return random.Next(20, 70); // generate ages 20, 21, ..., 68, 69
}
Now, we're left with the other 30%. I'd assume that there will be more young people than old people, so I'll attribute 20% to young people, and 10% to old people. We can update the code above to handle this:
double percentage = random.NextDouble();
if (percentage >= 0.3) // 1.0 - 0.3 = 70%
{
return random.Next(20, 70);
}
else if (percentage >= 0.1) // 0.3 - 0.1 = 20%
{
return random.Next(0, 20);
}
else // remaining 10%
{
return random.Next(70, 100);
}
Try it online - in the sample I bucket ages into the nearest 5 and then provide the count for the distribution.