当涉及到处理大整数和高精度小数计算时,Java 提供了两个非常有用的类,分别是 BigInteger
和 BigDecimal
。这两个类允许开发者处理超出标准数据类型范围的整数和高精度的小数,为金融、科学计算和密码学等领域提供了重要的支持。在本篇博客中,我们将深入探讨 BigInteger
和 BigDecimal
的用途、特性和使用方法。
BigInteger:处理大整数
BigInteger
是 Java 中用于处理大整数的类。它的主要特点包括:
1. 任意精度整数
BigInteger
允许你表示和操作远远超出标准整数范围的整数。这对于大型数据集合、密码学算法和精确计算等任务非常有用。
2. 不可变性
BigInteger
对象是不可变的,这意味着一旦创建,它们的值不可修改。任何对 BigInteger
的操作都将返回一个新的 BigInteger
对象,而不会改变原始对象。
3. 大量的运算方法
BigInteger
类提供了丰富的数学运算方法,包括加法、减法、乘法、除法、取余等等。这些方法可以用于执行各种大整数操作。
4. 创建方式
你可以使用构造函数传递字符串或者使用静态方法来创建 BigInteger
对象。这使得输入大整数变得非常灵活。
方式一:通过创建对象方式
BigInteger bigInt1 = new BigInteger("123456789012345678901234567890");
BigInteger bigInt2 = BigInteger.valueOf(987654321098765432109876543210L);
方式二:通过静态方法valueOf
BigInteger bigInteger = BigInteger.valueOf(123);
特点:BigInteger在范围-16-16中提前创建了对应的对象,也就是说通过valueOf方法得到的-16-16的对象都是创建好的。这样设计可以节省资源。
还有一点通过静态方法创建的对象的值的范围只能在Long范围中原因将在下面BigInteger是如何存储讲解
5 存储原理
BinInter可以存储的值的大小可以近似认为是无限的
BigInteger中有一个属性signum用来表示数字正负,为1表示正数,-1表示负数
BigInteger存储采用了mag数组,首先把数字的正负号去掉按照正数(转化为补码)处理(用signum来表示),
然后把数字转化为2进制,每32位为一组,然后把对应的十进制数存放在mag数组中(如果对源码反码补码不清楚可以看我的博客有关这段内容的详细介绍)
读取的时候再结合sIgnum就行了。
那么为什么静态方法只能存放long的大小以内的值呢
通过源码发现对于超过-16-16范围的值会调用构造方法
这个构造方法就是上面讲的原理。但是这里的mag数组最多只有两个,也就是说只能存2*32 64位数字,也就是long的大小。
BigDecimal: 高精度小数
问题:当我们输出0.2+0.3时可能会出现0.5...等数字,并不是0.5。这是因为计算机是以二进制方式存储,导致小数点后有许多位数都被省略了,但是BigDecimal可以解决这个问题
BigDecimal
类用于处理高精度小数,具有以下特点:
1. 任意精度小数
与 BigInteger
类似,BigDecimal
允许你表示和操作高精度的小数,避免了浮点数精度问题。
2. 不可变性
BigDecimal
对象也是不可变的,确保计算的精确性和一致性。
3. 高精度运算
BigDecimal
类提供了一系列高精度的算术运算方法,包括加法、减法、乘法、除法以及舍入操作。
4. 创建方式
参考BigInteger
注意这里对于-10-10之间的整数也是事先创建好的
5 存储原理
类似于BigInteger这里只不过是把每一位字符转化为ASCII表对应的值进行存储
BigDecimal
用于表示高精度的小数。- 内部存储:
BigDecimal
内部以十进制表示法存储小数。 - 它使用两个部分来存储小数:一个整数部分和一个小数部分。这些部分都以整数数组的形式存储。
- 与
BigInteger
类似,BigDecimal
也是不可变的,每个算术操作都返回一个新的BigDecimal
对象。
5. 示例用途
- 金融计算:在金融应用中,确保精确计算是至关重要的。
- 税务计算:处理需要高精度的税务计算。
- 科学和工程计算:需要高精度的浮点数运算。
不可变性:
对于BigInteger
和BigDecimal
,它们被设计成不可变的类,这意味着:
-
不可修改的值: 一旦创建了
BigInteger
或BigDecimal
对象,其内部的数值不能被修改。例如,如果你执行了一个加法操作,将两个BigInteger
相加,它将返回一个新的BigInteger
对象,而不会修改原始对象的值。 -
线程安全性: 不可变对象在多线程环境中更容易管理,因为它们不会被多个线程同时修改。这降低了并发编程中的错误风险。
-
预测性: 不可变对象的值在整个程序的执行期间保持不变,这使得程序更加可预测。
-
缓存友好性: 不可变对象可以安全地用于缓存,因为你知道它们不会在使用过程中改变。
如何理解不可变性的关键概念在于,每次对BigInteger
或BigDecimal
执行算术运算时,都会返回一个新的对象,而不会影响原始对象的值。这有助于确保数据的完整性和可靠性。
总结
在 Java 中,BigInteger
和 BigDecimal
类提供了处理大整数和高精度小数的强大工具。它们的不可变性、任意精度和丰富的运算方法使它们成为处理复杂数学问题和高精度计算的首选。无论是处理金融数据、密码学问题还是科学计算,BigInteger
和 BigDecimal
都能为开发者提供可靠的解决方案。如果你需要执行这些类型的操作,不妨考虑使用这两个类来确保计算的准确性和可靠性。