在随机挑选字符集之前洗牌是个好习惯吗

问题描述 投票:0回答:1

为了随机生成一个 N 长度的字符串,我在这里看到的几乎所有示例都使用了字母表之前的数字或数字之前的字母:

String alphanumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

对于这个列表,每个字符的索引是预先知道的(例如,索引 0 处的“A”,索引 1 处的“B”,...),即使我们选择一个随机整数来按字母数字中的索引号查找元素字符串。

我想知道在迭代中随机选择元素之前打乱字母数字字符是一个好习惯吗?

因此,字符将随机分布(不排序),没有人可以猜出顺序。

java string random
1个回答
0
投票

不。随机性不是这样运作的。您有效地提议:

“如果洗这副牌然后从中抽一张牌确实是随机的,想象一下如果我洗两次,它会变得多么随机!”。

只有当你的洗牌技巧很糟糕时,这才是正确的。只有两个选择:

  1. 考虑到洗牌后纸牌的实际顺序,我可以猜测你开始洗牌之前的顺序,这些猜测比随机赔率更好(“随机赔率”=我可以猜测最上面的牌是黑桃杰克。纯属偶然,我每 52 次这样的猜测就会正确一次,因为标准的一副牌有 52 张牌。如果我的猜测是基于洗牌后检查牌组,那么我会得到 优于 1/ 52 赔率,这就是我们在这里讨论的):然后你洗牌很糟糕。修复是为了更好。

  2. 在你洗牌后检查牌组的顺序绝对没有任何意义——它绝对没有说明你洗牌之前牌的顺序。这意味着您擅长洗牌。

鉴于#2,再次洗牌实际上是零点。

这同样适用于你的问题。只有2个选择:

  1. 从有效字符列表中选取任意值的算法是正确的。

  2. 这不合适。

在情况 #1 中,在随机挑选符号之前随机化符号的顺序是有道理的。对于第二种情况,这样做可能会有所帮助,但是,这不是您应该做的。相反,您应该修复“随机选择”算法!

或者,您可能处于计算机无法随机化的情况,因此,#2 门就是正在发生的情况,并且无法修复。但是,在这种情况下,您也不能以随机的方式打乱符号。

无论你尝试用哪种方式来推理这个问题都没关系:

想要先洗牌该列表永远是不正确的

那么什么是正确的算法?

String alphanumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; char randomChar = alphanumeric.charAt(rnd.nextInt(alphanumeric.length());

其中
rnd

java.util.Random

 的实例。根据发生的情况,您可能需要使用 
new SecureRandom()
 创建此实例。
我要挑选不换货

如果你想确保一个被拾取的角色不能被再次拾取,通常的方法是,特别是在这批东西中可以拾取的东西很少的情况下,将这批东西洗牌,然后只拾取该批东西。顶部。正确的做法是:

Random rnd = new SecureRandom(); // first put all elements in a list List<Character> list = new ArrayList<>(); for (int i = 0; i < alphanumeric.length(); i++) { list.add(alphanumeric.charAt(i); } // then shuffle it Collections.shuffle(list, rnd); // then just pick off the top: char firstPassChar = list.get(0); char secondPassChar = list.get(1); // and so on

再次,从这个打乱的列表中随机挑选的零点。它被洗牌了。位置 0 处的事物与“随机选择位置”处的事物一样随机。你无法将“100% 随机”变成更加随机的东西。
    

© www.soinside.com 2019 - 2024. All rights reserved.