32

Java工具类——数学相关的类

 3 years ago
source link: https://segmentfault.com/a/1190000023069337
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Java工具类——数学相关的类

在上一篇文章中,我们系统学习了 Java 里面的包装类,那么这篇文章,我们就来学习一下Java提供好的类——数学相关的类。

一、数学类介绍

在最早期学习 Java 基础语法结构的时候,其实我们学习并了解了加减乘除这些算数运算符,有了这些运算符,我们就可以做一些简单的运算了,但是当我们需要做一些比较复杂的运算的时候,其实用这些运算符是很难去处理的(比如获取随机数等等)。其实数学类对于我们并不陌生,在学习 Java 基础的时候,你一定用过 Math 类的,这个其实就是我们最早期接触的一个数学类了,其实与数学相关的类还有 BigInteger 类、BigDecimal 类等等,下面这个表格将这三个类做了一个小的梳理总结:

数学类 所属包 继承关系 Math类 java.lang包,不需要导包 默认继承Object基类 BigInteger类 java.math包,需要导包 继承自Number类,实现了Serializable, Comparable接口 BigDecimal类 java.math包,需要导包 继承自Number类,实现了Serializable, Comparable接口

下面我们就对这三种类做一个详细的学习。

二、Math类

其实看源码我们看到,Math 这个类是 final 修饰的,意思就是不能让子类去继承的,只能使用这个类。

public final class Math {}

下面,我们来详细了解一下Math类

1、Math类构造方法

通过看源码,我们可以得知 Math 这个类的构造方法是私有的,也就是我们是不能创建对象的,为什么会这样设计呢,其实是因为 Math 类里面的属性和方法都是静态的( static 修饰)。

/**
 * Don't let anyone instantiate this class.
 */
private Math() {}

2、Math类常用的方法

  • abs()方法 返回给定数的绝对值,方法提供了4个不同参数类型重载方法(int, long, float, double)
int abs1 = Math.abs(-1);
long abs2 = Math.abs(-3l);
float abs3 = Math.abs(-1.2f);
double abs4 = Math.abs(-3.923);
System.out.println(abs1);
System.out.println(abs2);
System.out.println(abs3);
System.out.println(abs4);
  • ceil()方法 返回大于或等于参数且等于一个数学整数的最小的双精度值,可以理解为向上取整。
System.out.println(Math.ceil(-1.3));//-1.0
System.out.println(Math.ceil(1.9));//2.0
System.out.println(Math.ceil(-7.9));//-7.0
System.out.println(Math.ceil(123));//123.0
  • floor()方法 返回最大的双精度值,该双精度值小于或等于参数,并且等于一个数学整数,可以理解为向下取整。
System.out.println(Math.floor(-1.3));//-2.0
System.out.println(Math.floor(1.9));//1.0
System.out.println(Math.floor(1.3));//1.0
System.out.println(Math.floor(-7.9));//-8.0
System.out.println(Math.floor(123));//123.0
  • round()方法 返回与参数最接近的整型数,四舍五入为正无穷,其实就是四舍五入的整数。
System.out.println(Math.round(-1.3));//-1
System.out.println(Math.round(1.9));//2
System.out.println(Math.round(1.3));//1
System.out.println(Math.round(-7.9));//-8
System.out.println(Math.round(123));//123
  • max()方法 返回最大值,该方法提供了4个不同参数类型重载方法(int,long,float,double)
System.out.println(Math.max(1, 3));//3
System.out.println(Math.max(-4, -5));//-4
System.out.println(Math.max(1.8, 1.92));//1.92
System.out.println(Math.max(-4f, -4f));//-4.0
  • min(a, b)方法 返回最小值,该方法提供了4个不同参数类型重载方法(int, long, float, double)
System.out.println(Math.min(1, 3));//1
System.out.println(Math.min(-4, -5));//-5
System.out.println(Math.min(1.8, 1.92));//1.8
System.out.println(Math.min(-4f, -4f));//-4.0
  • pow(a, b)方法 返回 a 的 b 次方,其中参数和返回值都是 double 类型的
System.out.println(Math.pow(3, 3));//27.0
System.out.println(Math.pow(3.2, 5));//335.5443200000001
  • random()方法 生成一个 double 类型的随机数,范围是[ 0.0, 1.0),注意是左闭右开。
System.out.println(Math.random());//0.4128879706448445
System.out.println(Math.random());//0.9024029619163387
System.out.println(Math.random());//0.4265563513755902

三、BigInteger类

我们都知道,在基本数据类型里面,long型的取值范围是最大的,也就是8个字节,取值范围是-2的63次方到正的2的63次方减去1,当然,这个取值范围很大很大,在平时的开发中,我们其中只用到int类型的都基本够了,但是当我们存储的数据的长度超过了 long 型的长度时,我们该怎么存储呢?这时候,BigInteger 类就可以解决我们的问题。

BigInteger 顾名思义,其实就是叫大整数,也就是说只能存储整型的数,我们通过构造方法和常用方法来了解BigInteger 类。

1、构造方法

BigInteger 类有8个构造方法,其中有2个私有构造方法。8个构造方法分别是:

private BigInteger(int[] val){}
private BigInteger(int signum, int[] magnitude){}
public BigInteger(byte[] val){}
public BigInteger(String val){}
public BigInteger(String val, int radix) {}
public BigInteger(int signum, byte[] magnitude){}
public BigInteger(int numBits, Random rnd){}
public BigInteger(int bitLength, int certainty, Random rnd){}

2、类中常用的方法

当我们想用这个类做四则运算的时候,是不是也可以直接加减乘除呢,比如下面这张图:

fARvyqm.png!web

通过上面这张图,BigInteger类直接做四则运算显然是不可以的,因为上面两个数是引用类型,而运算符只能对基本数据类型做运算。那么我们怎么做相应的四则运算呢?其实BigInteger类里面其实已经帮我们实现对应的方法,我们直接用实例化的的对象调用它就行了。比如下方的代码进行加减乘除:

private static void test6() {
    BigInteger num1 = new BigInteger("1111");
    BigInteger num2 = new BigInteger("2222");
    //加法
    BigInteger add = num1.add(num2);
    //减法
    BigInteger subtract = num2.subtract(num1);
    //乘法
    final BigInteger multiply = num1.multiply(num2);
    //除法(取整)
    BigInteger divide = num2.divide(num1);
    //除法(取余)
    BigInteger mod = num2.mod(num1);
    System.out.println(add);//3333
    System.out.println(subtract);//1111
    System.out.println(multiply);//2468642
    System.out.println(divide);//2
    System.out.println(mod);//0
  }

四、BigDecimal类

与 BigInteger 类对应的是 BigDecimal 类,BigInteger 是处理整数的,而 BigDecimal 是处理小数的,Decimal 英文单词就是小数的意思,所以 BigDecimal 顾名思义就是大小数,处理大的小数的。如果一个小数超过了 double类型的取值范围,就需要用到 BigDecimal。

1、构造方法

BigDecimal 类的构造方法有很多,最常用的是以下四个:

public BigDecimal(double val) {
public BigDecimal(int val) {}
public BigDecimal(String val) {}
public BigDecimal(long val) {}

2、类中常用的方法

和 BigInteger 类一样,BigDecimal 也是不可以直接进行加减乘除的,加减乘除的方式和 BigInteger 处理方式一样,比如下面的代码对BigDecimal 进行四则运算:

private static void test7() {
  BigDecimal num1 = new BigDecimal("1.23");
  BigDecimal num2 = new BigDecimal("2.46");
  //加法
  BigDecimal add = num1.add(num2);
  //减法
  BigDecimal subtract = num2.subtract(num1);
  //乘法
  final BigDecimal multiply = num1.multiply(num2);
  //除法(取整)
  BigDecimal divide = num2.divide(num1);

  System.out.println(add);//3.69
  System.out.println(subtract);//1.23
  System.out.println(multiply);//3.0258
  System.out.println(divide);//2
}

由于小数和整数不一样,小数经常涉及到精度的问题,所以 BigDecimal 里面也提供了方法来设置小数的精度,设置精度的方法有三个重载的方法:

public BigDecimal setScale(int newScale)
public BigDecimal setScale(int newScale, int roundingMode)
public BigDecimal setScale(int newScale, RoundingMode roundingMode)

这三个方法的第一个参数是设置保留小数点之后的位数,第二个参数是设置的模式(比如向上取整还是向下取整等等),设置四舍五入的模式有8种:

public final static int ROUND_UP =           0;
    
    public final static int ROUND_DOWN =         1;
    
    public final static int ROUND_CEILING =      2;
    
     public final static int ROUND_FLOOR =        3;
 
    public final static int ROUND_HALF_UP =      4;
   
    public final static int ROUND_HALF_DOWN =    5;
  
    public final static int ROUND_HALF_EVEN =    6;
    
    public final static int ROUND_UNNECESSARY =  7;

下面我们就来对这其中4种模式的用法做一个详细的分析

  • ROUND_UP 模式

UP的意思就是向上的意思,可以理解为加的意思。比如我保留了三位小数,那么我不管你后面的小数值如何(除了0),我都给你加一,就相当于四舍五入的五入。比如下面这个代码,我保留3为小数,模式设置为ROUND_UP模式,那么如果最后一位是0,那么结果就是9.461,否则就是9.462

BigDecimal bigDecimal = new BigDecimal("9.4610");
BigDecimal result = bigDecimal.setScale(3, BigDecimal.ROUND_UP);
  • ROUND_DOWN 模式

是一个舍位取值的概念,比如我保留了三位小数,那么我不管你后面的小数值如何,也不会四舍五入,就硬生生的的截断,相当于什么呢,就是我从小数点后面开始取三位,三位后面的都不要了。比如下面这个代码,我保留3为小数,模式设置为ROUND_DOWN模式,那么最后一位不管是什么(从0到9),最后的结果都是9.461

BigDecimal bigDecimal = new BigDecimal("9.4611");
BigDecimal result = bigDecimal.setScale(3, BigDecimal.ROUND_DOWN);
  • ROUND_CEILING 模式

这个模式就是给定的数如果为正数,行为和ROUND_UP一样,如果为负数,行为和ROUND_DOWN一样 。

  • ROUND_FLOOR 模式

这个模式就是给定的数如果为正数,行为和ROUND_DOWN一样,如果为负数,行为和ROUND_UP一样

五、小结

以上就是我对数学相关类的总结以及个人的理解,如果有任何不清楚的,可以去看官方文档(API官方文档地址: https://docs.oracle.com/javas... ),其实,很多人都很排斥看源码和阅读官网文档,原因就是源码和阅读官网文档都是全英文的,解读起来很费时间;其实这是一种不好的学习方式,源码和阅读官网文档是最官方权威的第一手资料,也是最正确的,如果我们去网上看其他的相关解读,这也只能是他人的解读,而其他人的解读就代表了他对源码和阅读官网文档的个人理解,而这个理解是可能会有出入的,也就是可能会误导我们,所以我们一定要养成习惯去阅读源码和阅读官网文档,可能刚开始的确很慢,但是慢慢的就你的阅读速度和效率就会提高的。

最后,最近很多小伙伴找我要 Linux学习路线图 ,于是我根据自己的经验,利用业余时间熬夜肝了一个月,整理了一份电子书。无论你是面试还是自我提升,相信都会对你有帮助!

免费送给大家,只求大家金指给我点个赞!

电子书 | Linux开发学习路线图

也希望有小伙伴能加入我,把这份电子书做得更完美!

有收获?希望老铁们来个三连击,给更多的人看到这篇文章


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK