【问题标题】:Range of values to populate randomly in loop在循环中随机填充的值范围
【发布时间】:2019-09-24 22:05:02
【问题描述】:

我正在尝试编写一种按排序顺序生成随机整数的方法,并且随机数的限制应该是输入数量的对数。当我做 10 个整数时,我编写的代码有效,所有正确的输出都得到 0。但是,如果我输入 100 或 1000,我不会得到值 0,1 或 0,1 和 2。我不知道为什么它的计算方式不正确,我只需要它来初始化整数在数组中作为数字的日志,但它不适用于大于 10 的任何东西。任何帮助将不胜感激,我在下面发布了代码。

public static void randomSortedLimited(ArrayList<Integer> inL,
                                                    int inHowMany) {

    inL.clear();
    int limit = (int) (Math.log10(inHowMany));
    //System.out.println(limit); added to make sure limit is calculated properly
    inL.add(0);
    for (int i = 1; i < inHowMany - 1; i++) {
        inL.add(i, inL.get(i-1) + new java.util.Random().nextInt(limit));
     }
}

输入:randomSortedLimited(emptyList, 10);

输出:[0,0,0,0,0,0,0,0,0,0]

输入:randomSortedLimited(empytList, 100);

输出:

[0, 1, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 15, 15, 15, 16, 16, 17, 17, 18, 19, 20, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 27, 28, 29, 30, 30, 30, 31, 31, 32, 32, 32, 32, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 40, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 50]
BUILD SUCCESSFUL (total time: 0 seconds)

【问题讨论】:

  • 可能会显示输出以帮助我们了解问题,使用 100 或 1000 值时会得到哪些意外输出。
  • 请解释您的输入是什么。 minimal reproducible example 会很有帮助。
  • 你的限制被超出了,我想,因为每次你创建一个新的整数时,你都会添加一些可能与限制一样大的东西,并将它添加到已经可能与限制一样大的东西。但正如巴达所说,输出会有帮助。
  • @azurefrog 我猜他或她首先清除列表,但我不明白将列表作为参数传递然后被清除的意义。为什么不在函数内部创建一个新列表?
  • @GitPhilter 嗯,我忽略了这一点。现在我更不知道这个方法应该做什么了。

标签: java arraylist random


【解决方案1】:

由于您不希望数字增加,因此不要执行 inL.get(i-1) + 部分。

为了获得更好的随机性,不要在循环内创建新的Random 对象。

要按排序顺序获取随机生成的数字,请在返回前调用sort()

这意味着你的代码应该是:

public static void randomSortedLimited(ArrayList<Integer> inL, int inHowMany) {
    int limit = (int) (Math.log10(inHowMany));
    Random random = new Random();
    inL.clear();
    for (int i = 0; i < inHowMany; i++) {
        inL.add(random.nextInt(limit));
    }
    Collections.sort(inL);
}

更新:来自comment

我不能使用 Collections.sort,因为调用太贵了。

不要在生成随机数时将它们添加到列表中,而是对它们进行计数,然后再添加。由于只有 limit 不同的整数,您可以使用计数器数组:

public static void randomSortedLimited(ArrayList<Integer> inL, int inHowMany) {
    int limit = (int) (Math.log10(inHowMany));
    
    // Generate and count random numbers
    Random random = new Random();
    int[] count = new int[limit];
    for (int i = 0; i < inHowMany; i++) {
        count[random.nextInt(limit)]++;
    }
    
    // Build list of random numbers in ascending order
    inL.clear();
    for (int i = 0; i < limit; i++) {
        Integer number = i; // autobox once
        for (int j = 0; j < count[i]; j++) {
            inL.add(number);
        }
    }
}

inHowMany = 1000 的示例输出,适用于上述两种解决方案

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 , 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2]

【讨论】:

  • 你可以只用一个循环吗?
  • @mickeyvolmouse 否
【解决方案2】:

这应该可行:

    public static void randomSortedLimited(int inHowMany) {

        ArrayList<Integer> inL = new ArrayList<Integer();
        int limit = (int) (Math.log10(inHowMany));
        //System.out.println(limit); added to make sure limit is calculated properly
        inL.add(0);
        for (int i = 1; i < inHowMany - 1; i++) {
            inL.add(i, (int)(Math.random() * (limit - inL.get(i - 1)) + inL.get(i - 1));
        }
    }

【讨论】:

  • 这种工作,但是对于 100 我得到一个 0,其余的是 1 或者对于 1000 我得到一个 0,其余的是 2 有没有办法让它更均匀?
  • 当然还有更多的方法可以做到这一点……我在 Andreas 的回答之后发布了一个。你能想出其他方法来做到这一点吗?想一想这是一个很好的练习......
  • 有没有办法只用一个循环来做到这一点?或者如果你想有不同的值,你必须做多个?
【解决方案3】:

检查 Math.log(您的表达式和类型转换)分别应用于 10 和 100 时返回的内容...并且 nextInt 返回的值在 0 和 一个小于 之间,比它的参数(日志表达式是什么) )。

【讨论】:

  • 哪个 OP 似乎完全理解,因为输入 10 (log = 1),OP 期望全 0,输入 100 (log = 2),OP 期望只有 0 和 1,并且输入1000 (log = 3),OP 需要 0、1 和 2。这个问题似乎与 log 的工作方式完全没有混淆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
相关资源
最近更新 更多