我正在尝试根据用户输入生成具有不同范围的随机数。在我的程序中,用户将输入iLvl作为1-100之间的数字,具体取决于该数字,我将生成一个适合等级范围的数字,并将其分配给preRoll,然后在论坛上打印出来。我遇到的问题是,无论我输入哪个号码,我都会得到相同的号码(仅从5到8不等)。我不确定为什么会发生这种情况,但我认为它必须对产生数字的系统时钟做一些事情。如果问题太模糊或基本没问题,我会道歉但是我在理解随机数生成器在c#中的工作原理时遇到了一些麻烦。感谢您的所有反馈,如果有任何其他问题,请告诉我
toss_number = input("How many times do you want to toss the coin?\n")
while True:
if toss_number.isdigit():
break
else:
toss_number = input("Please input NUMBER of times you want to toss a coin.\n")
答案 0 :(得分:3)
您在if语句中使用逻辑OR是错误的。
if(someNumber >= 1 || someNumber <= 4) // do things
所有数字都大于或等于1或小于或等于4,因此这个条件总是匹配的。由于您正在建立边界,因此您希望使用逻辑AND。
if(someNumber >= 1 && someNumber <= 4) // do things
这仅匹配数字1..4
。 3大于或等于1且小于或等于4,因此它匹配。 5大于或等于1,但也大于4,所以它不会超过你的条件。
答案 1 :(得分:1)
系统时钟并非用于生成随机数&#34; - 它用于为随机生成算法提供一次性种子值,以使其后续的数字序列基于。当您在非常接近的时间创建多个Random实例时,使用基于时间的种子值只是一个问题,然后期望每个实例使用不同的种子。这样的事情会显示问题:
Random rand1 = new Random();
Random rand2 = new Random();
Thread.Sleep(2000);
Random rand3 = new Random();
几乎可以肯定rand1和rand2将获得与另一个相同的随机数序列,而rand3赢了。但这不是问题 - 只需创建一个随机实例,并将其用于所有随机数,而不是多个实例(如果你不能保证他们不会有相同的基于时间的种子价值)。
在代码中,您可以创建getrandom实例,并在开头创建一个用于生成范围随机数的函数:
private static readonly Random getrandom = new Random();
public static int GenRan(int min, int max)
{
lock (getrandom) // synchronize
{
return getrandom.Next(min, max);
}
}
但你永远不会使用GenRan。而是在Click事件中创建一个新的随机对象:
Random obj = new Random();
虽然这看起来像某种错误,但它不会导致您描述的问题,因为您只需使用该对象生成每个随机数。所以内部,至少,似乎这可能会奏效。
由于有问题的代码在_Click方法中,我认为它是为事件调用的。每个方法调用最多生成一个随机数,并在每次调用时创建一个新的Random实例。似乎不太可能将UI事件处理程序调用得足够紧密,背靠背,以解决此问题。此外,问题不在于您获得了随机数的相同序列(这是多个随机实例创建的时间过于接近会发生的情况),但它并没有似乎是尊重Next方法的参数,它指示随机数的范围。因此,这与基于时间的种子价值完全没有任何关系。
所以这一切都是非常错误的。相反,它是错误的,因为条件语句被错误地写了。以下是您的代码中的一些内容:
if ( iLvl >= 1 || iLvl <= 4) // teir 8
{
preRoll = obj.Next(5, 9);
}
else if (iLvl >= 5 || iLvl <= 10) // teir 7
{
preRoll = obj.Next(10, 19);
}
else if (iLvl >= 11 || iLvl <= 17) // teir 6
{
preRoll = obj.Next(20, 29);
}
这是条件块开始的方式。让我们一起来看,值为3。
首先我们点击这个:
if ( iLvl >= 1 || iLvl <= 4) // teir 8
并且满足第一个条件 - iLvl&gt; = 1.并且其余条件是&#34;或者iLvl&lt; = 4&#34;。因此,满足任一条件将执行以下语句:
{
preRoll = obj.Next(5, 9);
}
请注意,这将完全描述您获得的结果范围。
如果您还没有看到问题,那就让我们继续前进,价值为6。
if ( iLvl >= 1 || iLvl <= 4) // teir 8
{
preRoll = obj.Next(5, 9);
}
else if (iLvl >= 5 || iLvl <= 10) // teir 7
{
preRoll = obj.Next(10, 19);
}
如果您希望第一个块为false,而第二个块为true,则会出现错误。 大于零,或任何值&lt;大于零的所有值都满足第一个块。当然,我们的新价值是&#34; 6&#34;大于零,因此需要第一个条件。实际上,所有值> 0将使用该条件,这就是您的问题。
要修复,您应该使用&#34;&amp;&amp;&#34;而不是&#34; ||&#34;,以确保满足块执行的条件。
答案 2 :(得分:0)
您正在检查AtomicInteger index = new AtomicInteger(1);
Map<String, Integer> nameMap = mySet.stream()
.sorted(myComparator)
.collect(Collectors
.toMap(MyObject::getName, value -> index.getAndIncrement(),
(e1, e2) -> e1, LinkedHashMap::new));
或iLvl >= 1
,所以除非iLvl小于1,否则这将始终为真。使用iLvl <= 4
(和)代替&&
(或)以确保两个条件均为真。
或者,你可以这样简化你的陈述:
||