java基础_函数Math.random()和Random的使用及区别

本文详细解析了Java中Math.random()方法与Random类的工作原理,包括它们如何生成随机数、构造函数的区别及其对随机性的影响。

我是野猪。

首先Math.random()是令系统随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值,是Java语言常用代码。例如:Number=Math.random()*3+1,设置一个随机1到4的变量;Random 类有含参数和不含参数的构造;其中不含参的构造方法每次都是使用当前系统时间作为种子,而含参构造是使用一个固定值(参数)作为种子(种子也就是Random生成随机数时使用的参数)。每次使用时先创建一个Random对象,也叫随机数生成器,然后调用Random.next**()方法获取数值。

我们存在的疑问有以下几个:
1.Math.random()使用方式;
2.Random的使用方式,有参和无参的区别,使用有参即种子时有何效果;
3.Random.nextInt(n) n的作用;
4.Math.random()和Random之间的关系;

具体的详解,将会有以下代码来辅助解释。

1.Math.random()使用方式:

	System.out.println("通过Math.random产生的随机数列");
        for (int j = 0; j < 8; j++) {
            System.out.println(Math.random() + ",");
        }

输出结果是:

通过Math.random产生的随机数列:

0.8168659689075662,
0.1840193556566645,
0.9640563597086169,
0.7561812266766494,
0.8666184559231468,
0.13803676499296735,
0.599042620405967,
0.11271421452403096,

产生的是double随机数列。

2.Random的使用方式:

首先产生的2个随机数生成器即Random对象,种子是100,代码如下:

       for (int i = 0; i < 2; i++) {
            //创建2个随机数生成器
            Random random = new Random(100);
            for (int j = 0; j < 3; j++) {
                //每个随机数生成器产生8个数
                //n 要返回的随机数的边界 也就是随机数的范围是0-50之间的整数
                System.out.println(random.nextInt(50) + ",");
            }
            System.out.println("");
        }
输出结果竟然一直:

15,

0,
24,


15,
0,
24,

由此可见,当使用有参数的构造创建随机数生成器然后生成随机数序列的时候,产生的随机数是种子经过计算得到的,具有相同种子数的Random对象生成的随机数序列相同。其次通过无参构造创建Random对象,其本质是也是种子,只不过种子不是具体的数值,而是系统当前的时间,也因此创建的随机数是不相同的。

代码如下:

    	System.out.println("Random不含种子参数\n");
        for (int i = 0; i < 2; i++) {
            //创建2个随机函数生成器
            Random random = new Random();
            for (int j = 0; j < 3; j++) {
                //每个随机数生成器产生3个数
                System.out.println(random.nextInt(50) + ",");
            }
            System.out.println("");
        }
输出结果:

Random不含种子参数
36,
7,
15,


33,
17,
13,

显然产生的随机数是不同的。

PS:random.nextInt (50)代表生成的随机数范围是0-50,不会越界。

我们进行源码分析,关于Random类,其构造源码如下:

    /**
     * Creates a new random number generator. This constructor sets
     * the seed of the random number generator to a value very likely
     * to be distinct from any other invocation of this constructor.
     */
    public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }
翻译大致:创建一个随机数生成器,此构造方法设置此随机数生成器的种子是独一无二的;

点击this,跳转到对应的有参构造中,显然由代码可以看出种子的生成和当前时间有关系,也因此这样生成的种子是独一无二的。

   public Random(long seed) {
        if (getClass() == Random.class)
            this.seed = new AtomicLong(initialScramble(seed));
        else {
            // subclass might have overriden setSeed
            this.seed = new AtomicLong();
            setSeed(seed);
        }
    }


通过比较我们就可以得出结论:
①随机数是种子经过计算生成的。
②Random类中不含参的构造函数每次都是使用当前时间作为种子,随机性更强;而含参数的构造函数是伪随机的,更有可预见性。
③具有相同种子值的Random对象生成的随机数相同;种子值不同,产生的随机数不再一致。

3.Math.random()和Random之间的关系:

查看源码:

public final class Math { 
     。。。。。省略
     public static double random() {
        return NoImagePreloadHolder.INSTANCE.nextDouble();
    }
     。。。。。省略
    private static class NoImagePreloadHolder {
        private static final Random INSTANCE = new Random();
    }

}
从Math类的源码就能看出Math.random()内部调用的方法就是Random类中的nextDouble()方法,此刻也就明确了文章一开始Math.random()返回的是double类型值。

总结:

java.util.Random类中

①随机数是种子经过计算生成的。
②Random类中不含参的构造函数每次都是使用当前时间作为种子,随机性更强;而含参数的构造函数是以参数为种子产生的伪随机数,更有可预见性。
③具有相同种子值的Random对象生成的随机数相同;种子值不同,产生的随机数不再一致。

Math.random()方法中内部调用的方法就是Random类中的nextDouble()方法。

如有错误,请大家及时指出。







<think>嗯,用户想要了解Java中的Math.random()函数使用教程。首先,我需要回顾一下这个函数的基本知识。Math.random()Java中用于生成伪随机数的方法,返回的是一个介于0(包含)1(不包含)之间的double值。也就是说,范围是[0,1)。这点很重要,得先讲清楚。 接下来,我应该考虑用户可能的应用场景。比如生成特定范围的随机整数或浮点数,或者进行概率模拟。用户可能需要具体的示例代码,所以需要准备几个常见的例子。例如,生成0到9的整数,或者生成1到100的随机数,甚至更复杂的范围,比如5到20之间的整数。 然后,需要解释Math.random()的工作原理。它内部其实是使用java.util.Random类的nextDouble()方法,所以可能会有线程安全问题吗?不过,在大多数情况下,Math.random()已经足够使用,但如果是多线程环境,可能需要用ThreadLocalRandom来代替,或者明确使用Random实例。这部分可能需要提及,但用户如果没有问到,可能不需要深入,但作为教程,应该提到替代方案。 另外,用户可能会想知道如何生成更复杂的随机数,比如不始于0的范围。比如生成一个[min, max)或者[min, max]之间的数。这时候需要给出公式,比如 (int)(Math.random() * (max - min)) + min 来得到左闭右开的区间,或者调整max - min +1来包含上限。 还要注意数据类型转换的问题,比如从double到int的强制转换会截断小数部分,所以需要确保用户理解这一点。例如,生成1到100的整数,正确的方法应该是(int)(Math.random() * 100) +1,而不是直接乘以100再转换,因为Math.random()不会达到1,所以乘以100后最大是99.999...,转换为int就是99,再加上1得到100,这样才是正确的闭区间[1,100]。 另外,可能需要提到Math.random()的局限性,比如它是线程安全但可能性能上不如其他方法,或者如果需要更高质量的随机数(比如安全相关的),应该使用SecureRandom类。不过这些属于进阶内容,可能用户暂时不需要,但可以简要提及。 最后,需要组织这些内容,结构清晰,分步骤讲解,从基本使用到示例,再到注意事项替代方案。确保用户能一步步跟着操作,理解每个例子的含义。同时,要检查代码的正确性,避免语法错误,比如括号是否正确,类型转换是否正确应用。 可能还需要对比一下Java不同版本中的变化,比如在Java 8之后是否有改进,但通常Math.random()的基本用法是保持不变的。此外,提醒用户如果需要重现随机数序列,可以使用种子,但Math.random()不允许设置种子,这时候应该使用Random类的实例,并通过构造函数传入种子。 总结一下,教程的结构大致是:函数的作用、基本用法、生成不同范围的随机数示例(整数浮点数)、注意事项(线程安全、替代类)、常见问题处理。确保每个部分都有代码示例解释,帮助用户理解应用。</think>以下是Java中`Math.random()`函数使用教程,分步骤讲解: --- ### **一、函数作用** `Math.random()` 是Java内置的静态方法,用于生成一个伪随机数,范围是 **[0,1)**(包含0,不包含1)。 --- ### **二、基本用法** 直接调用方法,返回一个 `double` 类型值: ```java double randomValue = Math.random(); System.out.println(randomValue); // 示例输出:0.5488135023048164 ``` --- ### **三、生成特定范围的随机数** #### **1. 生成 [0, N) 的整数** ```java int randomInt = (int) (Math.random() * N); // 示例:生成0~9的整数 int num = (int) (Math.random() * 10); ``` #### **2. 生成 [min, max) 的整数** 公式:`(int)(Math.random() * (max - min)) + min` ```java // 示例:生成5~19的整数(不包含20) int num = (int)(Math.random() * (20 - 5)) + 5; ``` #### **3. 生成 [min, max] 的整数** 公式:`(int)(Math.random() * (max - min + 1)) + min` ```java // 示例:生成1~100的整数(包含100) int num = (int)(Math.random() * 100) + 1; ``` #### **4. 生成指定范围的浮点数** ```java // 示例:生成10.0~20.0的浮点数 double num = Math.random() * 10 + 10; ``` --- ### **四、常见应用场景** #### **1. 概率模拟** ```java // 模拟50%概率事件 if (Math.random() < 0.5) { System.out.println("事件触发"); } ``` #### **2. 随机选择数组元素** ```java String[] colors = {"红", "蓝", "绿"}; int index = (int)(Math.random() * colors.length); System.out.println("随机颜色:" + colors[index]); ``` --- ### **五、注意事项** 1. **线程安全** `Math.random()` 内部使用 `java.util.Random` 类,多线程环境下建议改用 `ThreadLocalRandom`: ```java int num = ThreadLocalRandom.current().nextInt(1, 101); ``` 2. **更精确控制** 若需设置种子或更多方法,直接实例化 `Random` 类: ```java Random rand = new Random(); int num = rand.nextInt(100); // 生成0~99的整数 ``` --- ### **六、总结** - 简单随机数:直接使用 `Math.random()` - 范围整数:通过公式转换 - 高并发场景:优先选择 `ThreadLocalRandom` 或 `Random` 通过以上方法,可灵活应对Java中的随机数生成需求。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值