Java code for x random numbers that add up to n?
I'm making a music generation program and need a set of x random numbers selected from 0.125, 0.25 and 0.5 which add up to 1. I can't think of a neat way of doing this which also preserv开发者_如何学Ces the random element.
Thanks!
Just enumerate all possible combinations that sum up to 1 (it's not that many), and store them in an array. Then just calculate a random index number for that array to get a random combination.
There are 9 combinations which add up to 1. If you don't care about order at all, then you can just pick a random number between 1 & 9.
- {.5, .5}
- {.5, .25, .25}
- {.5, .25, .125, .125}
- {.5, .125, .125, .125,.125}
- {.25, .25, .25, .25}
- {.25, .25, .25, .125, .125}
- {.25, .25, .125, .125, .125, .125}
- {.25, .125, .125, .125, .125, .125, .125}
- {.125, .125, .125, .125, .125, .125, .125, .125}
If you care about order, then you want permutations. The set {.5, .25, .25} has 3! permutations:
- .5, .25, .25
- .5, .25, .25
- .25, .5, .25
- .25, .5, .25
- .25, .25, .5
- .25, .25, .5
However, you may only want the unique permutations to count.
- .5, .25, .25
- .25, .5, .25
- .25, .25, .5
For each of the sets, you could use an algorithm like this to generate the unique permutations. http://www.kerrywong.com/2006/04/14/generating-unique-permutations-programmatically/
Once you know all the permutations (or unique permutations), you could then use a random number to select one of the permutations.
If you care about extending the values later, you may want to consider a more dynamic approach. Avoid hardcoding values and logic. A solution like the following may help. In the below example, the max value 1 is configurable, as are the set of values which can be used to add up to the max. Load your list (from file or input) and then the program can run. This assumes your list was sorted from lowest to highest values before running.
public class MusicGeneration{
private List<Double> values = new ArrayList<Double>();
Random rand = new Random();
private double max_value = 0;
public MusicGeneration() {
max_value = 10;
values.add(0.125);
values.add(0.25);
values.add(0.5);
values.add(0.75);
}
private void createMusic() {
double total = 0;
while (total < max_value) {
int i = rand.nextInt(maxChoice(total));
System.out.println("Picked :: " + values.get(i));
total += values.get(i);
System.out.println("Total :: " + total);
}
}
private int maxChoice(double total) {
int size = values.size() - 1;
while (size > 0) {
if ((max_value - total) >= values.get(size)) {
System.out.println("Returning " + (size + 1));
return (size + 1);
}
size--;
}
return 1;
}
public static void main(String args[]) {
MusicGeneration play = new MusicGeneration();
play.createMusic();
}
}
Create an array that stores those three doubles: .125, .25, .5. Then generate a number 1-3, index into the array with it, and compare the result + your total so far to 1. If less, add them and continue. If equal, stop the program. If greater, generate another random index.
an iterative solution, which can easily be generalized if number of possibilities is too large.
just check which numbers can be legal at each step, and generate next number according to it.
java code:
static Random random = new Random();
public static double getRandom(double[] l) {
int i = random.nextInt(l.length);
return l[i];
}
public static List<Double> getRandNums() {
List<Double> l = new LinkedList<Double>();
double x = 1;
double[] arr1 = { 0.125, 0.25, 0.5 };
double[] arr2 = { 0.125, 0.25 };
double[] arr3 = { 0.125 };
double r;
while (x > 0) {
if (x >= 0.5) {
r = getRandom(arr1);
} else if (x >= 0.25) {
r = getRandom(arr2);
} else {
r = getRandom(arr3);
}
l.add(r);
x -= r;
}
return l;
}
精彩评论