java随机百分比
我需要生成n个百分比(0到100之间的整数),这样所有n个数字的总和加起来就是100java随机百分比,java,algorithm,math,random,Java,Algorithm,Math,Random,我需要生成n个百分比(0到100之间的整数),这样所有n个数字的总和加起来就是100 如果我只做了n次nextInt()n次,每次都确保参数为100减去之前累积的总和,那么我的百分比是有偏差的(即第一个生成的数字通常是最大的等等)。如何以无偏见的方式做到这一点?一旦您使用您描述的方法选择了数字,请重新排列数字的顺序。这样,最终的数字列表具有更均匀的分布 然而,请注意,无论你做什么,你都不能得到完全均匀的分布,因为一旦你开始选择数字,你的随机试验就不是独立的。见阿泰洛的答案 还要注意,您描述的算法
如果我只做了n次
nextInt()
n次,每次都确保参数为100减去之前累积的总和,那么我的百分比是有偏差的(即第一个生成的数字通常是最大的等等)。如何以无偏见的方式做到这一点?一旦您使用您描述的方法选择了数字,请重新排列数字的顺序。这样,最终的数字列表具有更均匀的分布
然而,请注意,无论你做什么,你都不能得到完全均匀的分布,因为一旦你开始选择数字,你的随机试验就不是独立的。见阿泰洛的答案
还要注意,您描述的算法可能不会提供所需的输出。最后一个数字不能是随机的,因为它必须使总和等于100。第一个明显的解决方案
do
int[] a = new int[n];
for (int i = 0; i < n; ++i) {
a[i] = random number between 0 and 100;
}
until sum(a) == 100;
do
int[]a=新的int[n];
对于(int i=0;i
就复杂性而言,它并不完美(达到和100的迭代次数可能相当大),但分布肯定是“无偏的”
编辑类似的问题:如何在半径为1、圆心为(0,0)的圆中生成随机点?解决方案:继续在范围(正方形)[-1..1,-1..1]中生成随机点,直到其中一个点与圆匹配:)生成任意范围的n个随机整数(称它们为
a[1]
。a[n]
)。将整数求和,并调用b
。您的百分比将是[a[1]/b,…,a[n]/b]
编辑:很好,将结果精确四舍五入到总数100是不平凡的。一种方法是将
1..n
中a[x]/b
的x
作为整数,然后随机分配剩余的单位100-(整数之和)
。我不确定这是否会在结果中引入任何偏差。准确地说,这取决于您希望样本无偏差的方式。这里有一个粗略的方法,它将粗略地给你一个好的结果
i=0生成n-1
整数,从0,…100,比如a[i]
到n-2
total
为这些数字的总和b[i]=楼层(100*a[i]/总计)
对于i=0,到n-2
b[n-1]=100-(b[0]+…b[n-2])
当然,如果你想更准确地做到这一点,你必须使用吉布斯抽样法或大都会黑斯廷斯法。你可能需要定义“偏差”的真正含义——但如果你所关心的只是数字的分布与它们的位置无关,那么你可以简单地以“偏差”的形式创建数字方法,然后随机化他们的位置 另一种“无偏”方法是创建n-1个随机百分比,对它们进行排序(称为x1 x2 x3…),然后将最终百分比定义为:
x1
x2 - x1
x3 - x2
...
100 - x(n-1)
这样,您将得到n个随机数,这些随机数相加到100。关键是生成0到100之间的n个随机数,但要将这些随机数用作“标记”,而不是要输出的最终数字序列。然后按升序遍历标记列表,计算每个百分比以输出为(当前标记-上一个标记) 这将提供比一次生成和输出每个数字更均匀的分布。 示例
import java.util.Random;
import java.util.TreeSet;
import java.util.SortedSet;
public class Main {
public static void main(String[] args) {
Random rnd = new Random();
SortedSet<Integer> set = new TreeSet<Integer>();
for (int i=0; i<9; ++i) {
set.add(rnd.nextInt(101));
}
if (set.last() < 100) {
set.add(100);
}
int prev = 0;
int total = 0;
int output;
for (int j : set) {
output = j - prev;
total += output;
System.err.println(String.format("Value: %d, Output: %d, Total So Far: %d", j, output, total));
prev = j;
}
}
}
做一个数组。在该数组的每个部分随机放置100%。 示例显示n=7
import java.util.Random;
public class random100 {
public static void main (String [] args) {
Random rnd = new Random();
int percents[] = new int[7];
for (int i = 0; i < 100; i++) {
int bucket = rnd.nextInt(7);
percents[bucket] = percents[bucket] + 1;
}
for (int i = 0; i < 7; i++) {
System.out.println("bucket " + i + ": " + percents[i]);
}
}
}
import java.util.Random;
公开课100{
公共静态void main(字符串[]args){
随机rnd=新随机();
整数百分比[]=新整数[7];
对于(int i=0;i<100;i++){
int bucket=rnd.nextInt(7);
百分比[桶]=百分比[桶]+1;
}
对于(int i=0;i<7;i++){
System.out.println(“bucket”+i+:“+percents[i]);
}
}
}
我遇到了一个类似的问题,并最终按照您所说的做了,生成了随机整数,最大为现有整数和极限之差。然后我随机化了整数的顺序。效果相当不错。这是一种遗传算法。一些答案建议选择随机百分比,并计算它们之间的差异。正如Nikita Ryback指出的那样,这并不能给出所有可能性的均匀分布;特别是,零的频率将低于预期
要解决这个问题,请考虑从100%开始并插入分隔符。我将以10为例进行演示:
% % % % % % % % % %
% % % % % % % % % %
我们可以在11个位置插入一个分隔符:在任意两个百分比之间或在开始或结束处。因此,插入一个:
% % % % / % % % % % %
% % % % / % % % % % %
这代表选择四和六。现在插入另一个分隔符。这一次,有12个位置,因为已经插入的分隔符创建了一个额外的位置。特别是,有两种方法可以
% % % % / / % % % % % %
% % % % / / % % % % % %
在上一个分隔符之前或之后插入。您可以继续此过程,直到您拥有所需数量的分隔符(比百分比数少一个)
% % / % / % / / % % % / % % % /
这对应于2,1,1,0,3,3,0
我们可以证明这是均匀分布。100分为k部分的成分数量是二项系数100+k-1选择k-1。就是
(100+k-1)(100+k-2)…101/(k-1)(k-2)*…*2*1
因此,选择任何特定构图的概率是该构图的倒数。当我们一次插入一个分配器时,首先我们从101个位置中选择,然后从102、103等位置中选择,直到达到100+k-1。
% % % % / / % % % % % %
% % / % / % / / % % % / % % % /
public static int[] randomBuckets(int total, int n_buckets) {
int[] buckets = new int[n_buckets];
Random rand = new Random();
for(int i=0;i<total;i++)
buckets[rand.nextInt(n_buckets)]++;
return buckets;
}
public static void main(String... args) {
for(int i=2; i<=10;i++)
System.out.println(Arrays.toString(randomBuckets(100, i)));
}
[55, 45]
[38, 34, 28]
[22, 21, 32, 25]
[28, 24, 18, 15, 15]
[17, 14, 13, 21, 18, 17]
[17, 19, 14, 15, 6, 15, 14]
[11, 14, 14, 14, 4, 17, 9, 17]
[13, 12, 15, 12, 8, 10, 9, 11, 10]
[11, 13, 12, 6, 6, 11, 13, 3, 15, 10]
System.out.println(Arrays.toString(randomBuckets(100000000, 100)));
[1000076, 1000612, 999600, 999480, 998226, 998303, 1000528, 1000450, 999529,
998480, 998903, 1002685, 999230, 1000631, 1001171, 997757, 1000349, 1000527,
1002408, 1000852, 1000450, 999318, 999453, 1000099, 1000759, 1000426, 999404,
1000758, 1000939, 999950, 1000493, 1001396, 1001007, 999258, 1001709, 1000593,
1000614, 1000667, 1000168, 999448, 999350, 1000479, 999991, 999778, 1000513,
998812, 1001295, 999314, 1000738, 1000211, 999855, 999349, 999842, 999635,
999301, 1001707, 998224, 1000577, 999405, 998760, 1000036, 1000110, 1002471,
1000234, 1000975, 998688, 999434, 999660, 1001741, 999834, 998855, 1001009,
999523, 1000207, 998885, 999598, 998375, 1000319, 1000660, 1001727, 1000546,
1000438, 999815, 998121, 1001128, 1000191, 998609, 998535, 999617, 1001895,
999230, 998968, 999844, 999392, 999669, 999407, 998380, 1000732, 998778, 1000522]
public static int[] randomNumbers(int numOfNumbers){
int percentN = numOfNumbers;
int[] intArray = new int[101];
//set up the array with values
for(int i = 0; i < intArray.length; i++){
intArray[i] = i;
}
//set up an array to hold the selected values
int[] selectionArray = new int[(percentN - 1)];
//run a for loop to go through and select random numbers from the intArray
for(int n = 0; n < selectionArray.length; n++){
int randomNum = (int)(Math.random() * 100);
selectionArray[n] = intArray[randomNum];
}
//bubble sort the items in the selectionArray
for(int out = (selectionArray.length - 1); out > 1; out--){
for(int in = 0; in < out; in++){
if(selectionArray[in] > selectionArray[in + 1]){
int temp = selectionArray[in];
selectionArray[in] = selectionArray[in + 1];
selectionArray[in + 1] = temp;
}
}
}
//create an array to hold the calculated differences between each of the values to create random numbers
int[] calculationArray = new int[percentN];
//calculate the difference between the first item in the array and 0
calculationArray[0] = (selectionArray[0] - 0);
//calculate the difference between the other items in the array (except for the last value)
for(int z = 1; z < (calculationArray.length - 1); z++){
calculationArray[z] = (selectionArray[z] - selectionArray[z - 1]);
}
//calculate the difference for the last item in the array
calculationArray[(calculationArray.length - 1)] = (100 - selectionArray[(selectionArray.length - 1)]);
return calculationArray;
}