Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java随机百分比_Java_Algorithm_Math_Random - Fatal编程技术网

java随机百分比

java随机百分比,java,algorithm,math,random,Java,Algorithm,Math,Random,我需要生成n个百分比(0到100之间的整数),这样所有n个数字的总和加起来就是100 如果我只做了n次nextInt()n次,每次都确保参数为100减去之前累积的总和,那么我的百分比是有偏差的(即第一个生成的数字通常是最大的等等)。如何以无偏见的方式做到这一点?一旦您使用您描述的方法选择了数字,请重新排列数字的顺序。这样,最终的数字列表具有更均匀的分布 然而,请注意,无论你做什么,你都不能得到完全均匀的分布,因为一旦你开始选择数字,你的随机试验就不是独立的。见阿泰洛的答案 还要注意,您描述的算法

我需要生成n个百分比(0到100之间的整数),这样所有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])
  • 然后b是结果的百分比数组

    最后一个是有偏见的,但其余的应该是一致的


    当然,如果你想更准确地做到这一点,你必须使用吉布斯抽样法或大都会黑斯廷斯法。

    你可能需要定义“偏差”的真正含义——但如果你所关心的只是数字的分布与它们的位置无关,那么你可以简单地以“偏差”的形式创建数字方法,然后随机化他们的位置

    另一种“无偏”方法是创建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;
    
    }