Java-随便写写-实现变量值交换和随机数的生成

0.开头

今天在看书的时候,随手把简单的减法程序又写了一下;如下:

import java.util.Random;
import java.util.Scanner;

import static java.lang.System.*;

public class SubtractionQuiz {
    public static void main(String[]args){
        int number1,number2;
        //创建[0,10)之间整数的第一种方法
        number1 = (int)(Math.random()*10);
        number2 = (int)(Math.random()*10);
        //不创建新变量的情况下,交换两个变量的值
        if(number1<number2){
            number1 = number2-number1;
            number2 = number2-number1;
            number1 = number2+number1;
        }
        Scanner input = new Scanner(System.in);
        System.out.println("What is "+number1+"-"+number2+":");
        int answer = input.nextInt();
        if(answer==(number1-number2)){
            System.out.println("Your answer is right!");
        }else{
            System.out.println("Your answer is wrong!");
        }
    }
}

  • 大概就是随机生成两个数,求他们相减的结果。
  • 虽然程序简单,但是其中涉及到的随机数和变量值交换值得记一下。
  • 当然,其中的变量值不需要交换也可以完成这个程序,这里只是针对这个书上的程序说一下。

1.随机数的生成

Java生成随机数通常有两种方法:Math.random()和Random类。

  • Math.random()方法
    这个方法返回[0,1)这个区间的double类型的数,注意是左闭右开
    看一下源码的注释:
    Returns a {@code double} value with a positive sign, greater than or equal to {@code 0.0} and less than {@code 1.0}.

  • Random类
    (1)通过创建Random类的实例,调用其中的方法可以实现多种数据类型数据的随机生成。
    (2)构造方法有两个,Random()Random(long seed),其中的参数被称为种子,如果不传入则默认以seedUniquifier()^System.nanoTime()【不知道这个nanoTime方法是什么的话,可以查看我的另一篇博客】为种子;
    源码如下:

 public Random() {
        this(seedUniquifier() ^ System.nanoTime());
    }
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);
        }
    }

我们暂时不管这里的种子seed问题,先看一下创建对象之后可以调用什么方法如何实现随机数。
这里给出方法表格:

方法解释
boolean nextBoolean()随机生成一个布尔值
double nextDouble()随机生成一个double值 ,范围是[0,1),这个方法和Math.random()效果一致
int nextInt()随机生成一个int值,范围是整个int取值范围,即[-2 ^ 31, 2 ^ 31-1]
int nextInt(int n)随机生成一个int值,范围是[0, n)

其他类似。
顺便附一下API图吧:
Random类API
程序实例如下:

import java.util.Random;

public class RandomDemo {
    public static void main(String[]args){
        Random random1 = new Random();
        Random random2 = new Random(10);
        System.out.println(random1.nextBoolean());
        System.out.println(random1.nextDouble());
        System.out.println(random1.nextInt());
        System.out.println(random2.nextInt());
        System.out.println(random1.nextInt(5));
    }
}

结果如下:

false
0.9248622022817408
1943808773
-1157793070
1

2.seed种子问题

已经基本解决了Math.random()和Random()的用法之后,我们来讨论一下seed到底是什么东东?????
引用一下其他大佬的结论https://www.cnblogs.com/greatfish/p/5845924.html:

种子就是产生随机数的第一次使用值,机制是通过一个函数,
将这个种子的值转化为随机数空间中的某一个点上,
并且产生的随机数均匀的散布在空间中。以后产生的随机数都与前一个随机数有关。

总之:种子确定的情况下,其实是可以推出或者说预测下面的数据的。所以我们说生成的随机数其实是伪随机数pseudorandom.不信的话,我们举个例子来看,创建两个种子一样的Random类。

import java.util.Random;

public class RandomDemo {
    public static void main(String[]args){
        Random random1 = new Random(10);
        Random random2 = new Random(10);
        System.out.println("random1生成的第一个数:"+random1.nextInt());
        System.out.println("random2生成的第一个数:"+random2.nextInt());
        System.out.println("random1生成的第二个数:"+random1.nextInt());
        System.out.println("random2生成的第二个数:"+random2.nextInt());
        System.out.println("random1生成的第三个数:"+random1.nextInt());
        System.out.println("random2生成的第三个数:"+random2.nextInt());
    }
}

结果如下:

random1生成的第一个数:-1157793070
random2生成的第一个数:-1157793070
random1生成的第二个数:1913984760
random2生成的第二个数:1913984760
random1生成的第三个数:1107254586
random2生成的第三个数:1107254586

我们发现相同的种子产生的随机数是一个固定的序列。
我们将程序稍微改一下:

import java.util.Random;

public class RandomDemo {
    public static void main(String[]args){
        Random random1 = new Random(10);
        Random random2 = new Random(10);
        System.out.println("random1生成的第一个数:"+random1.nextInt(100));
        System.out.println("random2生成的第一个数:"+random2.nextInt(100));
        System.out.println("random1生成的第二个数:"+random1.nextInt(100));
        System.out.println("random2生成的第二个数:"+random2.nextInt(100));
        System.out.println("random1生成的第三个数:"+random1.nextInt(100));
        System.out.println("random2生成的第三个数:"+random2.nextInt(100));
    }
}
random1生成的第一个数:13
random2生成的第一个数:13
random1生成的第二个数:80
random2生成的第二个数:80
random1生成的第三个数:93
random2生成的第三个数:93

结论是一样的!所以在使用的时候,其实不添加seed生成的随机数其实才更“随机”。

3.变量值交换的问题

本章先介绍两种常见的简单方法。

  • 引入temp第三个变量实现:
    这个比较好理解,如下:
int i1 = 88;
int i2 = 99;
int temp = i1;
i1 = i2;
i2 = temp;

但是这个方法需要创建temp变量,实际上不需要第三方变量也能实现。

  • 两个变量自身加减法实现(不引入第三个变量):
//减法
int number1 = 11;
int number2 = 33;
number1 = number2-number1;
number2 = number2-number1;
number1 = number2+number1;//加法
int number3 = 22;
int number4 = 66;
number3 = number4+number3;
number4 = number3-number4;
number3 = number3-number4;

我们仔细观察其实能看出来,上面这种不引入第三方变量的方法存在一个隐患。那就是如果number1-number2或者number3+number4存在[整数溢出]的风险。
比如下面这种情况:

public class ValueExchange {
    public static void  main(String[]args){
        int number3 = 2147483647;
        int number4 = 2147483647-2;
        System.out.println("Number3="+number3);
        System.out.println("Number4="+number4);
        number3 = number4+number3;
        System.out.println("Number3中间值="+number3);
        number4 = number3-number4;
        number3 = number3-number4;
        System.out.println("Number3="+number3);
        System.out.println("Number4="+number4);
    }
}
Number3=2147483647
Number4=2147483645
Number3中间值=-4
Number3=2147483645
Number4=2147483647

尽管最后交换的效果达到了,但是交换过程中出现了溢出的情况。
因此,这次留下两个问题,【第一个是溢出为什么不影响交换结果?】,【第二个是有没有其他方法实现变量值的交换?】。
下次再写!!!

### 回答1: jmu-java-随机数-使用蒙特卡罗法计算圆周率的值 蒙特卡罗法是一种通过随机抽样来解决问题的方法。在计算圆周率的问题中,我们可以通过随机生成点的方式来模拟落在圆内的点和落在正方形内但不在圆内的点的数量,从而得到圆的面积和正方形的面积,进而计算出圆周率的值。 在使用Java编写程序时,我们可以利用Java中的随机数生成器来生成随机点的坐标,然后通过判断点是否在圆内来计算圆内和圆外的点的数量。最后,根据圆的面积和正方形的面积的比例,计算出圆周率的值。 这种方法虽然简单,但是需要生成大量的随机点才能得到较为准确的结果。因此,在实际应用中,需要根据具体问题的要求来确定生成随机点的数量。 ### 回答2: 蒙特卡罗法是一种基于随机数的数值解法,其大致思想是利用概率统计原理构造随机过程,并利用随机过程解决计算问题。在计算圆周率时,可以使用蒙特卡罗法来估算其值。 具体来说,我们可以通过生成随机数的方式来模拟在一个正方形内部随机投点,将正方形视作一个包含在其中的圆的外接正方形,那么正方形内部的点有多少个落在圆的内部,就可以用这个数量来近似出圆的面积。根据圆的公式,可以通过这个近似面积来计算出圆的半径和周长,从而得出圆周率的值。 在实现上,我们可以使用Java中的Math类中的随机数函数来生成一堆随机点,然后统计其中有多少个点落在圆的内部。最终得到的比率就是圆的面积和正方形面积的比例,用这个比例乘以4就可以得到圆周率的值了。 然而,需要注意的是,这种随机投点的方法是一种概率性的计算方法,随着投点数量的增加,估算出的圆周率值会越来越接近实际值。因此,我们需要在程序中设置投点数量,以达到较为准确的计算结果。 总的来说,使用蒙特卡罗法计算圆周率的值是一种在计算中有很大应用价值的技术,特别适用于大量的模拟计算和参数估算。在Java中,通过使用Math类中的随机数函数,可以快速便捷地实现这种方法。 ### 回答3: JMU-Java是一种集成了Java语言与数学算法的库,通过使用随机数生成器可以使用蒙特卡罗法计算圆周率的值。这种方法利用了概率统计的思想,在一个较大的正方形内随机生成若干个点,并统计落在圆内的点的数量,然后通过数学公式计算圆周率的值。这个方法的精确度可以通过增加正方形内的点数来提高,因此随着正方形中点数的增大,计算出的圆周率会越来越接近真实值。 使用JMU-Java库进行计算时,可以通过以下步骤实现: 首先需要导入库文件,然后设置随机数发生器并选择生成点的数量和正方形的边长。然后,利用循环语句和if语句进行判断,统计出正方形内等分的子正方形和落在圆内的点的数量,然后通过公式计算出圆的面积和圆周率的值,并将结果输出。 使用蒙特卡罗法计算圆周率的优点是计算简单易懂,并且可以通过增加点的数量提高计算精确度。但是,它也存在一些缺点,如计算误差较大,需要大量计算,因此会消耗较多的时间和计算资源。另外,在使用时需要注意数据的范围和运算精度,以免影响计算结果的准确性。 总之,蒙特卡罗法计算圆周率的方法是一种简单、直观、易于实现的方法。通过使用JMU-Java库,可以方便地实现该方法,并且在学习编程和数学等方面都具有一定的帮助作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值