目录
背景:
BigInteger:
获取对象的方式有四种:
常用成员方法:
BigInteger 底层存储方式:
BigDecimal:
获取对象的方法
常用成员方法:
方法 5 中的舍入模式:
BigDecimal 的底层存储方式:
背景:
BigInteger和BigDecimal类在Java中的存在意义主要在于解决以下问题:
- 大整数运算:
BigInteger 类能够处理任意大小的整数,不受 Java 中基本类型(如 int、long)的最大值限制。这对于需要进行大整数计算的场景非常有用,比如在密码学、大素数分解、大数因子分解等算法中。
- 高精度浮点数运算:
BigDecimal 类则用于精确的小数或浮点数计算,尤其在金融、科学计算等领域特别重要。由于 Java 的基本类型 double 和 float,存在一定的精度限制且不支持完全精确的十进制表示。而 BigDecimal 可以提供任意精度的小数运算,确保结果准确无误,避免了因浮点数舍入误差带来的问题。
- 数值稳定性:
使用 BigDecimal 可以保证在涉及货币计算、比例计算或者要求绝对精确的情况下不会出现舍入误差,这在商业应用中至关重要。
- 数学运算完整性:
这两个类提供了丰富的算术运算方法,包括加减乘除、模运算、开方、指数、取余数等等,使开发者能方便地对大整数和高精度小数执行各种复杂的数学运算。
综上所述,BigInteger 和 BigDecimal 在无法满足基本数据类型范围和精度需求时,为程序提供了更强大的数值处理能力,确保了数值计算的准确性和完整性。
BigInteger:
获取对象的方式有四种:
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.maxmin 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 底层存储方式:
BIgInteger 为什么能存很大的数据?
其实在底层是用一个 int 类型的数组来存储,首先将这个很大的数据分成几段,从然后存入数组的不同位置。
我们用 dbug 模式验证一下,
1.
2.
3.
4.
当signum为-1时,表示该数为负;当signum为0时,表示该数为0;当signum为1时,表示该数为正数。
BigDecimal:
前言:
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
方法 5 中的舍入模式:
RoundingMode:
四舍五入最常用....
BigDecimal 的底层存储方式:
底层存储也是一个数组
biglnteger 采取分段存储,BigDecimal 采取的是遍历存储,
在 jdk 低版本下将遍历到的字符存入字符数组 Char[]
并用其对应得 Ascii 码值来记录
高版本 jdk 是用 byte 数组直接记录字符的 Ascii 码值