在Java中获取随机布尔值

88

好的,我已经将这个stackoverflow问题实现到我的代码中:Return True or False Randomly

但是,我遇到了奇怪的行为:我需要同时运行十个实例,每个实例每次运行只返回一次true或false。而令人惊讶的是,无论我做什么,每次都只得到false

有什么方法可以改进这种方法,以便我至少有大约50%的机会获得true吗?


为了更加易于理解:我将我的应用程序构建为JAR文件,然后通过批处理命令运行。

 java -jar my-program.jar
 pause

程序内容 - 为了尽可能简单:

public class myProgram{

    public static boolean getRandomBoolean() {
        return Math.random() < 0.5;
        // I tried another approaches here, still the same result
    }

    public static void main(String[] args) {
        System.out.println(getRandomBoolean());  
    }
}

如果我打开10个命令行并运行它,每次都会得到结果为false...


31
http://xkcd.com/221/ - aioobe
15
为什么不使用 Random r = new Random(); r.nextBoolean(); - Thomas Jungblut
11个回答

124

我建议使用Random.nextBoolean()

话虽如此,像您使用的Math.random() < 0.5也可以。这是在我的机器上的行为:

$ cat myProgram.java 
public class myProgram{

   public static boolean getRandomBoolean() {
       return Math.random() < 0.5;
       //I tried another approaches here, still the same result
   }

   public static void main(String[] args) {
       System.out.println(getRandomBoolean());  
   }
}

$ javac myProgram.java
$ java myProgram ; java myProgram; java myProgram; java myProgram
true
false
false
true

毋庸置疑,每次获取不同的值是无法保证的。然而在你的情况下,我怀疑

A) 你没有使用你认为的代码(比如编辑了错误的文件)

B) 在测试时你没有编译你的不同尝试,或者

C) 你正在使用一些非标准的损坏的实现。


48

您是否尝试查看Java文档

从此伪随机数生成器的序列中返回下一个伪随机、均匀分布的布尔值...truefalse值以(大约)相等的概率产生。

例如:

import java.util.Random;

Random random = new Random();
random.nextBoolean();

35

2
更多的是,我甚至尝试了 nextBoolean 方法,并得到了相同的结果(连续 10 次为 false)。显然,这个程序比我写的要复杂得多,所以要么我是一个非常幸运的人,要么就是一个真正愚蠢的程序员 :) - Pavel Janicek
@Pavel Janicek,然后连续10个false吗?还是总是得到false?我曾经在我写的一个C#项目中遇到过同样的问题,那里我在初始化部分做错了什么。我每次启动时都得到相同的结果。你能否也发布一下你的初始化代码呢?! - Sagi
2
好的,这里可能会有一个小问题!我没有正确地初始化该值 :) 至少给个赞... ;) - Pavel Janicek

11

Java 8: 使用隔离到当前线程的随机生成器:ThreadLocalRandom nextBoolean()

类似于Math类使用的全局Random生成器,ThreadLocalRandom使用一个内部生成的种子进行初始化,该种子可能无法修改。在适用时,与共享的Random对象相比,在并发程序中使用ThreadLocalRandom通常会遇到更少的开销和争用。

java.util.concurrent.ThreadLocalRandom.current().nextBoolean();

3
为什么不使用具有 nextBoolean 方法的 Random 类呢?
import java.util.Random;

/** Generate 10 random booleans. */
public final class MyProgram {

  public static final void main(String... args){

    Random randomGenerator = new Random();
    for (int idx = 1; idx <= 10; ++idx){
      boolean randomBool = randomGenerator.nextBoolean();
      System.out.println("Generated : " + randomBool);
    }
  }
}

1
您可以使用以下内容获得不偏倚的结果:
Random random = new Random();
//For 50% chance of true
boolean chance50oftrue = (random.nextInt(2) == 0) ? true : false;

注意: random.nextInt(2) 表示数字 2 是上界,计数从0开始。因此我们有2个可能的数字(0和1),因此概率为50%!

如果您希望结果更有可能为真(或假),可以按以下方式调整上述内容!

Random random = new Random();

//For 50% chance of true
boolean chance50oftrue = (random.nextInt(2) == 0) ? true : false;

//For 25% chance of true
boolean chance25oftrue = (random.nextInt(4) == 0) ? true : false;

//For 40% chance of true
boolean chance40oftrue = (random.nextInt(5) < 2) ? true : false;

0

你也可以生成两个随机整数并验证它们是否相同,这样可以更好地控制概率。

Random rand = new Random();

声明一个范围来管理随机概率。 在这个例子中,有50%的几率是真的。

int range = 2;

生成2个随机整数。

int a = rand.nextInt(range);
int b = rand.nextInt(range);

然后简单地比较并返回该值。

return a == b; 

我还有一个你可以使用的类。 RandomRange.java


0

用于灵活的布尔值随机生成器:

public static rbin(bias){
    bias = bias || 50;
    return(Math.random() * 100 <= bias);
    /*The bias argument is optional but will allow you to put some weight
      on the TRUE side. The higher the bias number, the more likely it is
      true.*/
}

确保使用数字0 - 100,否则可能会降低偏差并获得更多常见的false值。

PS:我对Java一无所知,除了它与JavaScript有一些共同特征。 我利用我的JavaScript知识和推理能力构建了这段代码。 请注意,我的答案可能不可用。 您可以编辑此答案以修复我不知道的任何问题。

你需要声明变量类型,或者使用 var 让编译器推断。 - undefined

0

文本中的单词总是一个随机源。给定某个单词,下一个单词不能推断出来。对于每个单词,我们可以获取其字母的ASCII码,将这些码相加得到一个数字。这个数字的奇偶性可以作为一个随机布尔值的良好候选者。

可能存在的缺点:

  1. 这种策略基于使用文本文件作为单词来源。在某个时刻,将到达文件的末尾。但是,您可以估计从应用程序中调用randomBoolean()函数的次数。如果您需要调用它约100万次,则拥有100万个单词的文本文件就足够了。作为更正,您可以使用来自在线报纸等实时来源的数据流。

  2. 通过对语言中常见短语和习语的一些统计分析,可以在一定程度上估计短语中的下一个单词,给出短语的前几个单词。但是从统计学上讲,我们能够准确预测下一个单词的情况很少。因此,在大多数情况下,下一个单词与前面的单词无关。

    包p01;

    import java.io.File; import java.nio.file.Files; import java.nio.file.Paths;

    public class Main {

    String words[];
    int currentIndex=0;
    
    public static String readFileAsString()throws Exception 
      { 
        String data = ""; 
        File file = new File("the_comedy_of_errors");
        //System.out.println(file.exists());
        data = new String(Files.readAllBytes(Paths.get(file.getName()))); 
        return data; 
      } 
    
    public void init() throws Exception
    {
        String data = readFileAsString(); 
        words = data.split("\\t| |,|\\.|'|\\r|\\n|:");
    }
    
    public String getNextWord() throws Exception
    {
        if(currentIndex>words.length-1)
            throw new Exception("out of words; reached end of file");
    
        String currentWord = words[currentIndex];
        currentIndex++;
    
        while(currentWord.isEmpty())
        {
            currentWord = words[currentIndex];
            currentIndex++;
        }
    
        return currentWord;
    }
    
    public boolean getNextRandom() throws Exception
    {
        String nextWord = getNextWord();
        int asciiSum = 0;
    
        for (int i = 0; i < nextWord.length(); i++){
            char c = nextWord.charAt(i);        
            asciiSum = asciiSum + (int) c;
        }
    
        System.out.println(nextWord+"-"+asciiSum);
    
        return (asciiSum%2==1) ;
    }
    
    public static void main(String args[]) throws Exception
    {
        Main m = new Main();
        m.init();
        while(true)
        {
            System.out.println(m.getNextRandom());
            Thread.sleep(100);
        }
    }
    

    }

在Eclipse中,我的项目根目录下有一个名为“the_comedy_of_errors”的文件(没有扩展名),是通过“File> New> File”创建的,在此处粘贴了一些内容:http://shakespeare.mit.edu/comedy_errors/comedy_errors.1.1.html

0

初始化随机数生成器最简单的方法是使用无参数构造函数,例如

Random generator = new Random();

然而,在使用此构造函数时,您应该认识到算法随机数生成器并不是真正的随机数,它们实际上是生成一系列固定但看起来随机的数字的算法。
您可以通过给Random构造函数传递“种子”参数来使其看起来更“随机”,例如使用毫秒级系统时间动态构建(这将始终不同)。

2
额,无参构造函数正是这样做的(至少大多数情况下是这样)。除非你知道自己在做什么,否则你很少需要直接设置种子。对于这种类型的问题几乎从不适用。而且它不会使序列看起来“更随机”。它只是一个不同的序列(绑定到种子),那么。 - Joey

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