在Java中,应用程序由类组成,类由方法和变量组成。变量又分为原始变量和引用变量。 Java中的变量有8种类型,除了
boolean
和之外char
,它们分为以下类型:
- 整数:
byte
、short
和int
;long
- 浮点数(也称为实数):
float
和double
。
long
,范围从 -9223372036854775808 到 9223372036854775807。浮点数中,double
的范围是 1.7e-308 到 1.7e+308。您可以在本文中阅读有关实数的更多信息。但是如果我们需要存储大于可接受范围的数字怎么办?在这种情况下,我们需要BigInteger
和BigDecimal
。
Java 中的大整数
Java 类BigInteger
用作任意长度整数值的模拟,没有 long 的 64 位限制。此外,它是 类 的后代Number
,就像数字简单类型的标准包装器 - 、 、Integer
等等Long
-因此它具有导致简单类型的方法的实现: Byte
Double
BigInteger value = new BigInteger("32145");
int intValue = value.intValue();//32145
long longValue = value.longValue();//32145
double doubleValue = value.doubleValue();//32145.0
我们立即看到这样一个对象的创建,BigInteger
并将我们的值传递给构造函数,但以字符串格式。值得注意的是,他拥有不止一位设计师,但适合所有场合。如果基本类型不能容纳来自 的全部数据BigInteger
,则数据将被截断为该基本类型的范围。但同时,这些方法也有类似的方法(intValueExact()
等等longValueExact()
),唯一的区别是,如果进行转换的简单类型不适应数据范围,则会抛出ArithmeticException。
大整数常量
对于内部使用,该类具有常量:BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
这些是常量对象BigInteger
,其值分别为0
、1
和10
。
大整数方法
该类的主要特征之一是它充满了在 Java 中实现标准算术运算的方法。例如:-
求和运算:
BigInteger firstValue = new BigInteger("37995"); BigInteger secondValue = new BigInteger("35466"); BigInteger resultValue = firstValue.add(secondValue);//73461
-
乘法运算:
BigInteger firstValue = new BigInteger("37995"); BigInteger secondValue = new BigInteger("35466"); BigInteger resultValue = firstValue.multiply(secondValue);//1347530670
-
一个数除以另一个数求余数的运算:
BigInteger firstValue = new BigInteger("37995"); BigInteger secondValue = new BigInteger("35466"); BigInteger resultValue = firstValue.remainder(secondValue);//2529
-
获取数字的绝对值(即模数、无符号):
BigInteger firstValue = new BigInteger("-37995"); BigInteger resultValue = firstValue.abs();//37995
-
mod计算的运算:
BigInteger firstValue = new BigInteger("-34"); BigInteger secondValue = new BigInteger("5"); BigInteger resultValue = firstValue.mod(secondValue); //1
-
获取随机数并指定结果值将使用的位数:
BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211 BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
-
按位移位运算(this >> n)
左移:
BigInteger firstValue = new BigInteger("5"); BigInteger firstResultValue = firstValue.shiftLeft(3);//40
右移:
BigInteger secondValue = new BigInteger("34"); BigInteger secondResultValue = secondValue.shiftRight(2); //8
Java 中的 BigDecimal
当我们需要任意长度的实数时,使用Java类 -BigDecimal
. 通常,它用于处理财务而不是double
,因为它提供了更多的自定义选项。与 和 一样BigInteger
,BigDecimal
是一个类的后代Number
,并且具有将对象的值返回为特定基元类型的方法:
BigDecimal value = new BigDecimal(35563.3);
long longValue = value.longValue();//35563
double doubleValue = value.doubleValue();//35563.3
正如我们所看到的,当减少到 时long
,仅保留整数部分,而小数部分被丢弃。
BigDecimal 构造函数
我们将仔细研究构造函数BigDecimal
,因为该类有更广泛的选择。有些构造函数允许您以不同的方式设置对象的值(通过传递int
、long
、double
,String
甚至BigInteger
),并且有些构造函数允许这样做。设置创建的对象的设置(舍入方法、小数位数):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
这里一切都清楚了,我们直接设置我们想要看到的数值和小数位数。
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
这个构造函数的结果可能非常不可预测,因为我们指定了一个 double,它本质上是一个非常模糊的类型。因此,一般建议在构造函数中使用String
。
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
我们设置了double
,但同时我们还设置了一个描述舍入规则的参数(其中包含小数位数和舍入的算法)。
char[] arr = new String("455656.545").toCharArray();
BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
我们设置一个字符数组,从哪个元素中获取对象的值以及我们获取多少个元素。
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
我们采用一个已经存在的对象BigInteger
,设置小数位数。
大十进制方法
该类BigDecimal
还包含各种算术运算的方法,但BigInteger
它没有处理位的方法,例如 . 但无论如何,主要特点BigDecimal
是处理浮点数的灵活性。让我们看看一些使我们能够掌握实数的技巧:
-
我们得到精度(数字的数量):
BigDecimal value = new BigDecimal("454334.34334"); int result = value.precision();//11
-
设置小数位数和舍入规则:
BigDecimal firstValue = new BigDecimal(3445.544445); BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_CEILING);//3445.545
下面我们将仔细研究一下设置舍入规则的常量。
-
除以
BigDecimal
另一个BigDecimal
,同时指明所需的小数位数和舍入规则:BigDecimal firstValue = new BigDecimal("455656.545"); BigDecimal secondValue = new BigDecimal(3445.544445); BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
-
将小数点向右/向左移动一定位数:
BigDecimal value = new BigDecimal("455656.545"); BigDecimal firstResult = value.movePointRight (2);//45565654.5 BigDecimal secondResult = value.movePointLeft (2);//4556.56545
-
修剪尾随零:
BigDecimal value = new BigDecimal("45056.5000"); BigDecimal result = value.stripTrailingZeros();//45056.5
如果实部全为零并且整个部分也全为零(或者根本没有小数位),那么:
BigDecimal value = new BigDecimal("450000.000"); BigDecimal result = value.stripTrailingZeros();//4.5E+5
BigDecimal 舍入规则
要设置舍入规则,在内部BigDecimal
我们可以看到描述舍入算法的特殊常量: ROUND_UP
- 从零舍入,向实部舍入:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_UP );//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UP );//-2.5
ROUND_DOWN
— 四舍五入到零,即截断实部:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_DOWN );//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_DOWN );//-2.6
ROUND_CEILING
— 四舍五入到正无穷大。也就是说,如果我们的数字是正数,则 -> ROUND_UP
,如果负数,则 ->ROUND_DOWN
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_CEILING);//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_CEILING);//-2.5
ROUND_FLOOR
- 四舍五入到负无穷大,也就是说,如果我们的数字是正数,则 -> ROUND_DOWN
,如果负数,则 ->ROUND_UP
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_FLOOR);//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_FLOOR);//-2.6
对于所考虑的值,我们将把这个截断小数位的最接近的数字视为所考虑的数字的最近邻居。例如,2.43 会比 2.5 更接近 2.4,但 2.48 会更接近 2.5。 ROUND_HALF_DOWN
- 四舍五入到“最近的邻居”。如果两个邻居与特定值等距,则四舍五入到零。等距是指,例如,当四舍五入的数字为 5 时,与 0 和 10 的距离相同):
BigDecimal firstValue = new BigDecimal("2.58");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.6
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.5
ROUND_HALF_UP
— 向“最近邻居”舍入的模式。如果两个邻居等距,则进行舍入(这与我们在学校教的舍入相同):
BigDecimal firstValue = new BigDecimal("2.53");
BigDecimal firstResult = firstValue.setScale(1, BigDecimal.ROUND_HALF_UP );//2.5
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_UP );//2.6
ROUND_HALF_EVEN
— 如果两个邻居不等距,则四舍五入到“最近的邻居”。在这种情况下,如果要舍入的数字前面是奇数,则向上舍入,如果是偶数,则向下舍入:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
我们得到这个结果是因为在四舍五入时,5 会查看前一个数字 2,发现它是偶数,就会向下舍入。但如果:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
由于最后 5 个值查看前一个值并看到奇数,因此该舍入会向上舍入。结果,数字向上舍入为 6,之后下一个 6 也将舍入。但六不再看左边的数字,因为这个数字明显更靠近上方,结果最后的2加了1。 ROUND_UNNECESSARY
- 用于检查该数字是否不需要四舍五入。也就是说,我们检查数字是否具有所需的小数位数:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult = firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
这里一切都很好,该值有两位数,我们检查小数点后只有两位数。但如果:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
然后我们得到 - ArithmeticException
,因为被测试的值超出了指定的小数位数。但是如果我们检查两位小数,但实际上有一位,那么就不会抛出异常,并且将丢失的数字简单地用零补充:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY );//2.500
我还想指出 y具有与常量、和BigDecimal
类似的常量。这是文档的链接。最后:正如您可能注意到的那样,当对对象和执行操作时,我们不会更改旧对象,而是总是获取新对象。这告诉我们,它们在创建后是不可更改的,就像 一样。换句话说,它们的所有方法都不能改变对象的内部状态;最多只能返回一个新对象,其参数由我们正在使用的函数指定。 BigInteger ZERO
ONE
TEN
BigInteger
BigDecimal
immutable
String
GO TO FULL VERSION