目录
背景:
BigInteger:
获取对象的方式有四种:
常用成员方法:
BigInteger 底层存储方式:
BigDecimal:
获取对象的方法
常用成员方法:
方法 5 中的舍入模式:
BigDecimal 的底层存储方式:
背景:
BigInteger和BigDecimal类在Java中的存在意义主要在于解决以下问题:
- 大整数运算:
BigInteger 类能够处理任意大小的整数,不受 Java 中基本类型(如 int、long)的最大值限制。这对于需要进行大整数计算的场景非常有用,比如在密码学、大素数分解、大数因子分解等算法中。
- 高精度浮点数运算:
BigDecimal 类则用于精确的小数或浮点数计算,尤其在金融、科学计算等领域特别重要。由于 Java 的基本类型 double 和 float,存在一定的精度限制且不支持完全精确的十进制表示。而 BigDecimal 可以提供任意精度的小数运算,确保结果准确无误,避免了因浮点数舍入误差带来的问题。
- 数值稳定性:
使用 BigDecimal 可以保证在涉及货币计算、比例计算或者要求绝对精确的情况下不会出现舍入误差,这在商业应用中至关重要。
- 数学运算完整性:
这两个类提供了丰富的算术运算方法,包括加减乘除、模运算、开方、指数、取余数等等,使开发者能方便地对大整数和高精度小数执行各种复杂的数学运算。
综上所述,BigInteger 和 BigDecimal 在无法满足基本数据类型范围和精度需求时,为程序提供了更强大的数值处理能力,确保了数值计算的准确性和完整性。
3 种构造方法:
4 为静态方式获取对象:
构造方法 123 示例:
public class Test01 {
public static void main(String[] args) {
//1.[0,2^2-1],注意都是闭区间
BigInteger bd1=new BigInteger(2,new Random());
//2.当不知道数字多大时使用(可大于long),字符串中必须是整数
BigInteger bd2=new BigInteger("99999999999999999999999999999999");
//3. //细节:
//1将指定进制的数换成十进制
//2字符串中必须是整数
//3且不超出进制范围
BigInteger bd3 = new BigInteger("1110", 8);
System.out.println(bd3);//584
方法 4 示例:
//4.静态方法获取Big Integer的对象。
//表示范围为long
BigInteger bd4 = BigInteger.valueOf(9223372036854775807L);
//(超出Int返回添加L表示long)
----------------------------------
//内部有优化:
//-16-16做了优化,提前创建好了对象,若多次获取不会创建新的,目的是节约内存
BigInteger bd5 = BigInteger.valueOf(16);
BigInteger bd6 = BigInteger.valueOf(16);
System.out.println(bd5 == bd6);//true,前后地址一样
BigInteger bd7 = BigInteger.valueOf(17);
BigInteger bd8 = BigInteger.valueOf(17);
System.out.println(bd7 == bd8);//false,前后地址不一样
//System.out.println(Long.MIN_VALUE);//-9223372036854775808
//System.out.println(Long.MAX_VALUE);//9223372036854775807
valueOf 源码:
构造方法 2、4 最常用,
2 接收的是字符串,4 接收的是 long 类型
总结:
注意点:在进行 BigInteger 的运算时,不是直接使用对象来运算,而是用对象来调用方法来进行运算。
BigInteger 方法使用示例:
BigInteger bd1= BigInteger.valueOf(10);
BigInteger bd2= BigInteger.valueOf(3);
//1.add
BigInteger bd3 = bd1.add(bd2);
System.out.println(bd3);//13
//2.subtract
BigInteger subtract = bd1.subtract(bd2);
System.out.println(subtract);//7
//3.multiply
BigInteger multiply = bd1.multiply(bd2);
System.out.println(multiply);//30
//4.divide
BigInteger divide = bd1.divide(bd2);
System.out.println(divide);//3(整数相除小数不保留)
//5.[]divide And Remainder--用数组存储
BigInteger[] b = bd1.divideAndRemainder(bd2);
System.out.println(b[0]);//3-商
System.out.println(b[1]);//1-余数
//6.equals在BigInteger中已经重写(比较数值)
BigInteger bd5= BigInteger.valueOf(10);
BigInteger bd6= BigInteger.valueOf(10);
boolean results = bd5.equals(bd6);
System.out.println(results);//true
//7.pow--括号内只能填int
BigInteger pow = bd1.pow(2);
System.out.println(pow);//100--bd1的2次幂
//8.max\min
BigInteger max = bd1.max(bd2);
System.out.println(max);//10
//*注意*
System.out.println(max==bd1);//true
//9.intValue,longvalue....
//要遵守类型范围
BigInteger a = BigInteger.valueOf(99);
long i = a.longValue();// <--
System.out.println(i);
BIgInteger 为什么能存很大的数据?
其实在底层是用一个 int 类型的数组来存储,首先将这个很大的数据分成几段,从然后存入数组的不同位置。
我们用 dbug 模式验证一下,
1.
2.
3.
4.
当signum为-1时,表示该数为负;当signum为0时,表示该数为0;当signum为1时,表示该数为正数。
前言:
System.out.println(0.09+0.01);
System.out.println(0.216-0.1);
System.out.println(0.226*0.01);
System.out.println(0.09/0.1);
控制台:
0.09999999999999999
0.11599999999999999
0.0022600000000000003
0.8999999999999999
直接的运算出现了精度丢失的情况:
这是为什么?
因为计算机是使用二进制来运算的,在我们输入十进制小数后得到的二进制数有可能很长(因为进制转换乘 R 取整)如下面几个小数:
,而 对于 double 类型来说,小数部份的位数是有限的(52 位)
那么这时 0.226 就要有 3 位 不得不被舍弃了,所以造成了数据的不准确
实际开发中涉及金融,证券等对数字精度要求高的场景,为解决精度丢失问题,就有了BigDecimal。
2 种构造:
3 为静态方式获取
构造方法示例:
//1.通过传递double小数来创建对象
//仍然有可能不精确·,所以不建议使用
BigDecimal bd1=new BigDecimal(0.01);
BigDecimal bd2=new BigDecimal(0.09);
System.out.println(bd1);
System.out.println(bd2);
//0.01000000000000000020816681711721685132943093776702880859375
//0.0899999999999999966693309261245303787291049957275390625
//2通过传递字符串表示的小数来创建对象(当较大的小数)
//建议使用·
BigDecimal bd3=new BigDecimal("0.01");
BigDecimal bd4=new BigDecimal("0.09");
System.out.println(bd3);
System.out.println(bd4);
// 0.01
// 0.09
System.out.println(bd3.add(bd4));//0.10
静态获取对象
//3.通过静态方法获取对象(当较小的小数)
BigDecimal bd6 = BigDecimal.valueOf(10);//传递整数也可以
System.out.println(bd6);//10
//和BigInteger一样内部有优化
//如果我们创建的是0-10之间的整数(包含0,10)
//那么会返回已经创建好的对象,不会再new
BigDecimal bd7=BigDecimal.valueOf(10);
BigDecimal bd8=BigDecimal.valueOf(10);
System.out.println(bd7==bd8);//true
// (6.0之类的是小数)
BigDecimal bd7=BigDecimal.valueOf(6.0);
BigDecimal bd8=BigDecimal.valueOf(6.0);
System.out.println(bd7==bd8);//false
//若要表示的数较小,不超过double取值范围,用静态方法创建对象
//要表示的数较大,超过double取值范围,用构造方法创建对象
BigDecimal bd1=BigDecimal.valueOf(10.0);
BigDecimal bd2=BigDecimal.valueOf(3.0);
//1.add
BigDecimal bd3 = bd1.add(bd2);
System.out.println(bd3);//13.0
//2.subtract
BigDecimal bd4 = bd1.subtract(bd2);
System.out.println(bd4);//7.0
//3.cheng
BigDecimal bd5=bd1.multiply(bd2);
System.out.println(bd5);//30.0
//4.chu
BigDecimal divide = bd1.divide(bd2);//除不尽则使用下面方法
System.out.println(divide);
//余五位小数,并四舍五入
BigDecimal bd6 = bd1.divide(bd2, 5, RoundingMode.HALF_UP);
System.out.println(bd6);//3.33333
RoundingMode:
四舍五入最常用....
底层存储也是一个数组
biglnteger 采取分段存储,BigDecimal 采取的是遍历存储,
在 jdk 低版本下将遍历到的字符存入字符数组 Char[]
并用其对应得 Ascii 码值来记录
高版本 jdk 是用 byte 数组直接记录字符的 Ascii 码值