9.3 和数学相关的类
9.3.1 Math类
java.lang.Math
类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。
- public static final double PI:返回圆周率
double pi = Math.PI;
public static double abs(double a)
:返回 double 值的绝对值。
double d1 = Math.abs(-5); //d1的值为5 double d2 = Math.abs(5); //d2的值为5
public static double ceil(double a)
:返回大于等于参数的最小的整数。
double d1 = Math.ceil(3.3); //d1的值为 4.0 double d2 = Math.ceil(-3.3); //d2的值为 -3.0 double d3 = Math.ceil(5.1); //d3的值为 6.0
public static double floor(double a)
:返回小于等于参数最大的整数。
double d1 = Math.floor(3.3); //d1的值为3.0 double d2 = Math.floor(-3.3); //d2的值为-4.0 double d3 = Math.floor(5.1); //d3的值为 5.0
public static long round(double a)
:返回最接近参数的 long。(相当于四舍五入方法)
long d1 = Math.round(5.5); //d1的值为6.0 long d2 = Math.round(5.4); //d2的值为5.0
- public static double pow(double a,double b):返回a的b幂次方法
- public static double sqrt(double a):返回a的平方根
- public static double random():返回[0,1)的随机值
- public static double max(double x, double y):返回x,y中的最大值
- public static double min(double x, double y):返回x,y中的最小值
double result = Math.pow(2,31); double sqrt = Math.sqrt(256); double rand = Math.random();
练习
请使用Math
相关的API,计算在 -10.8
到5.9
之间,绝对值大于6
或者小于2.1
的整数有多少个?
public class MathTest { public static void main(String[] args) { // 定义最小值 double min = -10.8; // 定义最大值 double max = 5.9; // 定义变量计数 int count = 0; // 范围内循环 for (double i = Math.ceil(min); i <= max; i++) { // 获取绝对值并判断 if (Math.abs(i) > 6 || Math.abs(i) < 2.1) { // 计数 count++; } } System.out.println("个数为: " + count + " 个"); } }
9.3.2 java.util.Random
用于产生随机数
- public Random():创建一个新的随机数生成器。此构造方法将随机数生成器的种子设置为某个值,该值与此构造方法的所有其他调用所用的值完全不同。(没有真正的随机数,需要种子产生随机数,同一个种子产生的伪随机数序列相同)
- public Random(long seed):使用单个 long 种子创建一个新的随机数生成器。该种子是伪随机数生成器的内部状态的初始值,该生成器可通过方法 next(int) 维护。
- boolean nextBoolean():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 boolean 值。
- void nextBytes(byte[] bytes):生成随机字节并将其置于用户提供的 byte 数组中。
- double nextDouble():返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 double 值。
- float nextFloat():返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 float 值。
- double nextGaussian():返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的 double 值,其平均值是 0.0,标准差是 1.0。
- int nextInt():返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
- int nextInt(int n):返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
- long nextLong():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
@Test public void test03(){ Random r = new Random(); System.out.println("随机整数:" + r.nextInt()); System.out.println("随机小数:" + r.nextDouble()); System.out.println("随机布尔值:" + r.nextBoolean()); }
9.3.3 BigInteger
不可变的任意精度的整数。
- BigInteger(String val)
- BigInteger add(BigInteger val)
- BigInteger subtract(BigInteger val)
- BigInteger multiply(BigInteger val)
- BigInteger divide(BigInteger val)
- BigInteger remainder(BigInteger val)
- int intValue():将此 BigInteger 转换为 int。
- long longValue():将此 BigInteger 转换为 long。
- float floatValue():将此 BigInteger 转换为 float。
- …
@Test public void test01(){ // long bigNum = 123456789123456789123456789L; BigInteger b1 = new BigInteger("123456789123456789123456789"); BigInteger b2 = new BigInteger("78923456789123456789123456789"); // System.out.println("和:" + (b1+b2));//错误的,无法直接使用+进行求和 System.out.println("和:" + b1.add(b2)); System.out.println("减:" + b1.subtract(b2)); System.out.println("乘:" + b1.multiply(b2)); System.out.println("除:" + b2.divide(b1)); System.out.println("余:" + b2.remainder(b1)); }
9.3.4 BigDecimal
不可变的、任意精度的有符号十进制数。
- BigDecimal(String val)
- BigDecimal add(BigDecimal val)
- BigDecimal subtract(BigDecimal val)
- BigDecimal multiply(BigDecimal val)
- BigDecimal divide(BigDecimal val)
- BigDecimal divide(BigDecimal divisor, int roundingMode)
- BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
- BigDecimal remainder(BigDecimal val)
- double doubleValue():将此 BigDecimal 转换为 double。
- …
@Test public void test02(){ /*double big = 12.123456789123456789123456789; System.out.println("big = " + big);*/ BigDecimal b1 = new BigDecimal("123.45678912345678912345678912345678"); BigDecimal b2 = new BigDecimal("7.8923456789123456789123456789998898888"); // System.out.println("和:" + (b1+b2));//错误的,无法直接使用+进行求和 System.out.println("和:" + b1.add(b2)); System.out.println("减:" + b1.subtract(b2)); System.out.println("乘:" + b1.multiply(b2)); System.out.println("除:" + b1.divide(b2,20,RoundingMode.UP));//divide(BigDecimal divisor, int scale, int roundingMode) System.out.println("除:" + b1.divide(b2,20,RoundingMode.DOWN));//divide(BigDecimal divisor, int scale, int roundingMode) System.out.println("余:" + b1.remainder(b2)); } //保留两位小数的方式: @Test public void test02(){ double f = 111231.5585; BigDecimal bg = new BigDecimal(f); double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); System.out.println(f1); }
9.4 日期时间API
9.4.1 java.util.Date
new Date():当前系统时间
long getTime():返回该日期时间对象距离1970-1-1 0.0.0 0毫秒之间的毫秒值
new Date(long 毫秒):把该毫秒值换算成日期时间对象
@Test public void test5(){ long time = Long.MAX_VALUE; Date d = new Date(time); System.out.println(d); } @Test public void test4(){ long time = 1559807047979L; Date d = new Date(time); System.out.println(d); } @Test public void test3(){ Date d = new Date(); long time = d.getTime(); System.out.println(time);//1559807047979 } @Test public void test2(){ long time = System.currentTimeMillis(); System.out.println(time);//1559806982971 //当前系统时间距离1970-1-1 0:0:0 0毫秒的时间差,毫秒为单位 } @Test public void test1(){ Date d = new Date(); System.out.println(d); }
9.4.2 java.util.Calendar
Calendar
类是一个抽象类,它为特定瞬间与一组诸如 YEAR
、MONTH
、DAY_OF_MONTH
、HOUR
等 日历字段
之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。与其他语言环境敏感类一样,Calendar
提供了一个类方法 getInstance
,以获得此类型的一个通用的对象。
(1)getInstance():得到Calendar的对象
(2)get(常量)
@Test public void test6(){ Calendar c = Calendar.getInstance(); System.out.println(c); int year = c.get(Calendar.YEAR); System.out.println(year); int month = c.get(Calendar.MONTH)+1; System.out.println(month); //... } @Test public void test7(){ TimeZone t = TimeZone.getTimeZone("America/Los_Angeles"); //getInstance(TimeZone zone) Calendar c = Calendar.getInstance(t); System.out.println(c); }
9.4.3 java.text.SimpleDateFormat
SimpleDateFormat用于日期时间的格式化。
@Test public void test10() throws ParseException{ String str = "2019年06月06日 16时03分14秒 545毫秒 星期四 +0800"; SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E Z"); Date d = sf.parse(str); System.out.println(d); } @Test public void test9(){ Date d = new Date(); SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E Z"); //把Date日期转成字符串,按照指定的格式转 String str = sf.format(d); System.out.println(str); }
9.4.4 JDK8后日期类
Java1.0中包含了一个Date类,但是它的大多数方法已经在Java 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:
- 可变性:象日期和时间这样的类对象应该是不可变的。Calendar类中可以使用三种方法更改日历字段:set()、add() 和 roll()。
- 偏移性:Date中的年份是从1900开始的,而月份都是从0开始的。
- 格式化:格式化只对Date有用,Calendar则不行。
- 此外,它们也不是线程安全的等。
可以说,对日期和时间的操作一直是Java程序员最痛苦的地方之一。第三次引入的API是成功的,并且java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了 Joda-Time (第三方开发)的精华,以一个新的开始为 Java 创建优秀的 API。
- java.time – 包含值对象的基础包
- java.time.chrono – 提供对不同的日历系统的访问。
- java.time.format – 格式化和解析时间和日期
- java.time.temporal – 包括底层框架和扩展特性
- java.time.zone – 包含时区支持的类
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于时钟(Clock),本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。
1、LocalDate、LocalTime、LocalDateTime
本地日期时间类
方法 | 描述 |
now() / now(ZoneId zone) | 静态方法,根据当前时间创建对象/指定时区的对象 |
of() | 静态方法,根据指定日期/时间创建对象 |
getDayOfMonth()/getDayOfYear() | 获得月份天数(1-31) /获得年份天数(1-366) |
getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
getMonth() | 获得月份, 返回一个 Month 枚举值 |
getMonthValue() / getYear() | 获得月份(1-12) /获得年份 |
getHours()/getMinute()/getSecond() | 获得当前对象对应的小时、分钟、秒 |
withDayOfMonth()/withDayOfYear()/withMonth()/withYear() | 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象 |
with(TemporalAdjuster t) | 将当前日期时间设置为校对器指定的日期时间 |
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours() | 向当前对象添加几天、几周、几个月、几年、几小时 |
minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours() | 从当前对象减去几月、几周、几天、几年、几小时 |
plus(TemporalAmount t)/minus(TemporalAmount t) | 添加或减少一个 Duration 或 Period |
isBefore()/isAfter() | 比较两个 LocalDate |
isLeapYear() | 判断是否是闰年(在LocalDate类中声明) |
format(DateTimeFormatter t) | 格式化本地日期、时间,返回一个字符串 |
parse(Charsequence text) | 将指定格式的字符串解析为日期、时间 |
@Test public void test7(){ LocalDate now = LocalDate.now(); LocalDate before = now.minusDays(100); System.out.println(before);//2019-02-26 } @Test public void test06(){ LocalDate lai = LocalDate.of(2019, 5, 13); LocalDate go = lai.plusDays(160); System.out.println(go);//2019-10-20 } @Test public void test05(){ LocalDate lai = LocalDate.of(2019, 5, 13); System.out.println(lai.getDayOfYear()); } @Test public void test04(){ LocalDate lai = LocalDate.of(2019, 5, 13); System.out.println(lai); } @Test public void test03(){ LocalDateTime now = LocalDateTime.now(); System.out.println(now); } @Test public void test02(){ LocalTime now = LocalTime.now(); System.out.println(now); } @Test public void test01(){ LocalDate now = LocalDate.now(); System.out.println(now); }
2、指定时区日期时间:ZonedDateTime
常见时区ID:
Asia/Shanghai UTC America/New_York
import java.time.ZoneId; import java.time.ZonedDateTime; public class TestZonedDateTime { public static void main(String[] args) { ZonedDateTime t = ZonedDateTime.now(); System.out.println(t); ZonedDateTime t1 = ZonedDateTime.now(ZoneId.of("America/New_York")); System.out.println(t1); } }
3、持续日期/时间:Period和Duration
Period:用于计算两个“日期”间隔
public static void main(String[] args) { LocalDate t1 = LocalDate.now(); LocalDate t2 = LocalDate.of(2018, 12, 31); Period between = Period.between(t1, t2); System.out.println(between); System.out.println("相差的年数:"+between.getYears());//1年 System.out.println("相差的月数:"+between.getMonths());//又7个月 System.out.println("相差的天数:"+between.getDays());//零25天 System.out.println("相差的总数:"+between.toTotalMonths());//总共19个月 }
Duration:用于计算两个“时间”间隔
public static void main(String[] args) { LocalDateTime t1 = LocalDateTime.now(); LocalDateTime t2 = LocalDateTime.of(2017, 8, 29, 0, 0, 0, 0); Duration between = Duration.between(t1, t2); System.out.println(between); System.out.println("相差的总天数:"+between.toDays()); System.out.println("相差的总小时数:"+between.toHours()); System.out.println("相差的总分钟数:"+between.toMinutes()); System.out.println("相差的总秒数:"+between.getSeconds()); System.out.println("相差的总毫秒数:"+between.toMillis()); System.out.println("相差的总纳秒数:"+between.toNanos()); System.out.println("不够一秒的纳秒数:"+between.getNano()); }
4、DateTimeFormatter:日期时间格式化
该类提供了三种格式化方法:
预定义的标准格式。如:DateTimeFormatter.ISO_DATE_TIME;
ISO_DATE
本地化相关的格式。如:DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
自定义的格式。如:DateTimeFormatter.ofPattern(“yyyy-MM-dd hh:mm:ss”)
@Test public void test(){ LocalDateTime now = LocalDateTime.now(); //预定义的标准格式 DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME;//2019-06-06T16:38:23.756 //格式化操作 String str = df.format(now); System.out.println(str); } @Test public void test1(){ LocalDateTime now = LocalDateTime.now(); //本地化相关的格式 // DateTimeFormatter df = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);//2019年6月6日 下午04时40分03秒 DateTimeFormatter df = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);//19-6-6 下午4:40 //格式化操作 String str = df.format(now); System.out.println(str); } @Test public void test2(){ LocalDateTime now = LocalDateTime.now(); //自定义的格式 DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E 是这一年的D天"); //格式化操作 String str = df.format(now); System.out.println(str); } //把字符串解析为日期对象 public void test3(){ //自定义的格式 DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy.MM.dd"); //解析操作 LocalDate parse = LocalDate.parse("2020.12.12", pattern); System.out.println(parse); }
Java 核心类API(下):https://developer.aliyun.com/article/1491133