生成一个随机数,要么是0,要么是1的问题

17

我需要一个随机数,可以是0或1,并将其作为下面代码中的返回值返回给main()函数。

import java.util.Scanner;
public class Exercise8Lab7 {
    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);

        int numFlips = 0;
        int heads = 0;
        int tails = 0;
        String answer;


        System.out.print("Please Enter The Number Of Coin Tosses You Want: ");
        numFlips = input.nextInt();

        for(int x = 1;x <= numFlips; x++){
            if(coinToss() == 1){
                answer = "Tails";
                tails++;
            }
            else{
                answer = "Heads";
                heads++;
            }
            System.out.print("\nCoin Toss " + x + ": " + answer);
        }
        System.out.println("\n\n====== Overall Results ======" +
        "\nPercentage Of Heads: " + (heads/numFlips)*100 + "\nPercentage Of Tails: " + (tails/numFlips)*100);
    }

    public static int coinToss(){
        double rAsFloat = 1 * (2 + Math.random( ) );
        int r = (int)rAsFloat;
        return r;
    }
}

已经有很多解决方案建议使用util.Random选项,我已经这样做了并且完美地运行,但我想弄清楚为什么我无法使其工作。显然,我希望数字是一个int类型,所以在生成随机数后将其转换为int类型。但无论我将Math.random()加上什么值或乘以什么值,它总是全部为正面或负面。从未混合。


1
1 * 应该已经是一个提示,让你意识到你做错了,因为将任何东西乘以1并没有什么作用。 - ajb
1
Random有一个带有上限的.nextInt()版本。否则,只需生成一个随机整数并对其进行%2操作。 - fge
1
因为 Math.random() + 2 生成的随机数在 2.0 和 2.9 之间。这个范围内的任何数字都不会等于 1。如果你只对 0 或 1 感兴趣,请使用 Math.round(Math.random()) - Hunter McMillen
1
感谢所有回答的人!我只是将Math.random()乘以2,现在它为正面和反面给我随机答案。问题是最后一个打印语句中的正面百分比和反面百分比根本不起作用,它们总是都等于0... - alannm37
11个回答

20

试一下)它会生成数字01

 Math.round( Math.random() )  ;

3
不鼓励提供仅有代码或是"试试看"的回答。 - RamenChef
1
这将生成双精度浮点数值。示例:1.0 - John Joe

19

你可以根据 Math.random() 的值作为介于 0.0 和 1.0 之间的双精度浮点数,使用布尔值 0 或 1,并使随机生成器更加简单。这样,你就可以完全摆脱 coinToss() 方法。

if(Math.random() < 0.5) {
    answer = "Tails";
    tails++;
}

移除硬币抛掷方法,并将第一个条件语句替换为上述代码。

Math.random();单独使用会返回0.0到1.0之间的值,但不包括1.0本身。如果该值在下半部分[0.0, 0.5)内,则它与上半部分[0.5, 1.0)内的概率相同。因此,您可以将下半部分中的任何值设置为true,将上半部分中的值设置为false。


10

很奇怪没有人使用取模除法来生成随机数。 这是最简单的实现方式:

Random rand = new Random();
int randomValue = rand.nextInt() % 2;

随机数可以是负数,因此输出不一定是0和1。 - littleb

5

Math.round(Math.random())会返回0.0和1.0两个值。由于这两个值都在int范围内,所以可以将它们强制转换为int类型。

public static int coinToss(){
    return (int)Math.round(Math.random());
}

3

(int)(Math.random()*2)在这种情况下也可以正常工作


1
为什么这个答案会被踩?这是几十年来最好的(如果不是最广泛传播的)答案。 - saferJo

2
问题可以转化为布尔生成,具体如下:
public static byte get0Or1 {

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

if(res)return 1;
else return 0;

}

2
由于您使用的是整数运算,它无法正常工作,调用2 + Math.Random几乎总是给出介于0.0和1.0之间的答案。
因此,假设您收到0.25作为结果,则您的计算如下:
double d = 1* (2 + 0.25); // (result = 2  

然后你正在检查你的结果是否等于1(它永远不会)。

更好的结果是将java.util.Random声明为类变量,并调用random.nextBoolean(),并在上面执行头/尾计算。

如果您继续使用Math.random()并且假设

return Math.random() < 0.5

由于Java API规范中指定“返回大于等于0.0且小于1.0的正数double值”,因此Math.random()无法返回1.0,这会稍微影响您的结果。


1
我不认为结果会有偏差。如果我理解正确,Math.random() 可能返回的值小于 0.5 的数量 恰好 等于大于等于 0.5 的可能返回值的数量。不过我得对算法进行研究以确保百分之百正确。 - ajb
2
这实际上是一个很棒的问题,比评论更重要。让我们看看我能否将其适应评论的空间(对于格式的缺乏表示歉意)。之前的Java版本对零有巨大的偏见(函数为:((((long)next(27) << 27) + next(27)) / (double)(1L << 54);),因此在后来的版本中,他们通过微小的数学变化减少了偏见(((((long)(next(26)) << 27) + next(27)) / (double)(1L << 53);))。因此,通过减少第一个随机数的位数(但保持移位的大小),他们引入了一种微小的偏差-续- - Damian Nikodem
2
在原始代码中,浮点数内部尾数的最低位存在偏差,为0(比不是0的情况多3倍),因此通过这个“小”更改,他们能够消除该偏差,但会产生略微向中心上方偏移的偏差,这比具有给定固定位的偏差要好。下一个方法也有其自身的内部偏差,这使得问题更加复杂。如果您详细查看javadoc,应该会注意到输出是“近似”均匀的,有两种证明方法,第一种是简单地强制执行-连续- - Damian Nikodem
2
使用两个for循环调用next函数两次,并返回所有结果的列表(这将非常耗时),但是可以让您绘制结果的直方图。否则,如果懒惰(并且时间有限),创建一个循环来运行“抛硬币”算法并计算结果,您应该会注意到真和假之间比例的“偏斜”随着时间的推移而增加。 - Damian Nikodem
1
非常有趣!我得找时间进一步研究一下(希望能够有时间……)。 - ajb

2

Math.random() 返回一个随机浮点数,范围在[0.0,1.0)之间--这意味着结果可以是从0到1.0的任何值,但不包括1.0。

您的代码

double rAsFloat = 1 * (2 + Math.random( ) );

将这个数字取在[0.0,1.0)范围内;加上2得到的是[2.0,3.0)范围内的数字;乘以1没有任何有用的作用;然后,当你将其截断为整数时,结果总是2。
要从这种随机函数中获取整数,需要计算可以返回多少不同的整数,然后将随机数乘以该值。如果您想要“0或1”的答案,则范围是2个不同的整数,因此将Math.random()乘以2:
double rAsFloat = 2 * Math.random();

这将为您提供在范围[0.0,2.0)内的随机数,当使用 (int) 截断到整数时,它可以是 0 或 1。如果您想要返回例如 1 或 2 的内容,您只需将其加上 1 即可:

double rAsFloat = 1 + 2 * Math.random();

我想你已经知道了Random类可以更轻松地获得所需的结果。但是,我还是决定解释一下这个问题,因为有一天你可能会在某种老语言的遗留系统上工作,需要使用[0.0,1.0)的随机值。(好吧,也许这种情况不太可能再发生了,但谁知道呢。)


1

这是我发现的最简单的方法,而不使用java.util.Random。

引用

Scanner input = new Scanner (System.in);

System.out.println("Please enter 0 for heads or 1 for tails");

int integer = input.nextInt();

input.close();

int random = (int) (Math.random() + 0.5);

if (random == integer) {
    System.out.println("correct");
}
else {
    System.out.println("incorrect");
}
System.out.println(random);

这将从(0到.99)中获取一个随机双精度数,并加上.5使其变为(.5到1.49)。它还会将其转换为int,这将使其变为(0到1)。最后一行是用于测试的。


0
 for(int i=0;i<100;i++){
System.out.println(((int)(i*Math.random())%2)); 
    }

使用模块会对你有所帮助!


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