在给定的范围内生成一个奇数随机数

7

如何在给定范围内生成一个奇数随机数?

例如:在1到6的范围内,随机数可以是3、1或5。

生成随机数的方法:

    Random_No = Min + (int)(Math.Random()*((Max-Min)+1))

参考如何在Java中生成特定范围内的随机整数?

生成奇数随机数的方法:

    Random_No = Min + (int)(Math.Random()*((Max-Min)+1))
    if(Random_No%2 ==0)
    {
          if((Max%2)==0)&&Random_No==Max)
          {
              Random_No = Random_No - 1;  
          }
          else{
              Random_No = Random_No +1;
          }
    }

这个函数总是将2转换成3而不是1,我们能否使这个函数更随机一些,有时将2转换为3,有时将2转换为1?


1
另一种方法是生成从0到2((6-1)/2)的数字,然后将结果加倍再增加。很容易将其推广到以任何数字开头的范围。 - BlueRaja - Danny Pflughoeft
10个回答

7
假设max是包含在内的,我建议采用以下方式:
if (Max % 2 == 0) --Max;
if (Min % 2 == 0) ++Min;
Random_No = Min + 2*(int)(Math.random()*((Max-Min)/2+1));

它会使所有奇数之间分布均匀。

2
实际上,romedius 做了聪明的事情;我只是稍微整理了一下编辑,不小心但不可避免地得到了过多的赞誉。您可以在修订历史记录中查看谁做了什么(单击“编辑”标签旁边的时间)。 - Jonathan Leffler
@CrazyCasta,你不需要第一行代码,其中你减少了Max的值。 - rouble
很好的解决方案。但是为什么我们需要 "if (Min % 2 == 0) ++Min" 这句话呢?我认为我们不需要改变 Min 的值吧? - user3369592

2

如果你想在方向上包含随机性,可以使用相同的随机数。

  int  randomDirection = Min + (int)(Math.Random()*((Max-Min)+1));
  if(randomDirection%2==0) {  // any condition to switch the direction 
      Random_No = Random_No + 1;  
  } else {
      Random_No = Random_No - 1;  
  }

1
为此,您需要生成第二个伪随机数以添加或减去1。
Random_No = Min + (int)(Math.Random()*((Max-Min)+1))
repartitionNumber =(int)(Math.Random()*((2)) // between 0 and 1
if(Random_No%2 ==0)
{
      if(Random_No+1<=Max && Random_No-1>=Min)
      {
          if(repartitionNumber==0)
              Random_No = Random_No + 1; 
          else
              Random_No = Random_No - 1;  
      }
      else if(Random_No+1<=Max)
          Random_No = Random_No + 1;
      else if (Random_No-1>=Min)
          Random_No = Random_No - 1;
}

1

不要生成0到6之间的随机数,而是生成0到5之间的随机数并向上取整到最近的奇数,这样你就会得到完美的分布(每种可能性(1、3、5)都有33%的概率)


1

我想知道为什么其他答案都使用int转换来生成随机数。为什么不直接生成随机整数,这比实数方法更准确呢?

Random rn = new Random();
if(maximum % 2 == 1) maximum = maximum + 1; // turn right bound to even
if(minimum % 2 == 0) minimum = minimum - 1; // turn left bound to odd
int range = (maximum - minimum + 1) / 2;
int randomNum =  rn.nextInt(range) * 2 + minimum;

1

要从整数生成奇数,您可以使用n * 2 + 1。实际上,您正在生成随机数并随后应用转换。

int num = min / 2 + random.nextInt((max + 1) / 2 - min / 2);
num = num * 2 + 1;

即使范围是 [1,5] [2,5] [2,6] [1,6],这也能正常工作。


0

在Java 1.7或更高版本中,我会使用ThreadLocalRandom

import java.util.concurrent.ThreadLocalRandom;

// Get odd random number within range [min, max]
// Start with an odd minimum and add random even number from the remaining range
public static int randOddInt(int min, int max) {
    if (min % 2 == 0) ++min;
    return min + 2*ThreadLocalRandom.current().nextInt((max-min)/2+1);
}

// Get even random number within range [min, max]
// Start with an even minimum and add random even number from the remaining range
public static int randEvenInt(int min, int max) {
    if (min % 2 != 0) ++min;
    return min + 2*ThreadLocalRandom.current().nextInt((max-min)/2+1);
}

使用ThreadLocalRandom的原因在这里有解释。另外请注意,我们在调用ThreadLocalRandom.nextInt()时将输入值+1是为了确保最大值包含在范围内。


0

让四舍五入取决于一个随机的 epsilon。

    Random_No = Min + (int)(Math.Random()*((Max-Min)+1))
    if(Random_No%2 ==0)
    {

          if((Max%2)==0)&&Random_No==Max)
          {
              Random_No = Random_No - 1;  
          }
          else{
              epsilon = Math.Random();
              if(epsilon > 0.5)
                  Random_No = Random_No + 1;
              else
                  Random_No = Random_No - 1;
          }
    }

0

从数学上讲,在最后一步四舍五入不会对数字产生任何影响。相反,第一个和最后一个数字与所有其他数字相比,被选中的概率要低50%。

建议采用CrazyCasta或J.A的解决方案。


0

检查Math.random()的返回值是否为浮点数。如果其整数部分是偶数,则根据其小数部分进行上下转换。例如:

假设Math.random()返回x.y;如果x是偶数,则返回(y>=0.5)?(x+1):(x-1)

这样会随机一点吗?


我想这就是我的问题所在...我希望从x到y范围内的所有数字具有相等的概率。 - Sanket

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接