Java BigDecimal 教程展示了如何使用 BigDecimal 在 Java 中执行高精度计算。
BigDecimal
表示一个不可变的、任意精度的带符号十进制数。用于高精度运算。 BigDecimal
提供算术运算、缩放操作、舍入、比较、散列和格式转换操作。
BigDecimal
由两部分组成:
例如,BigDecimal
2.18 的未缩放值为 218,小数位数为 2。
BigDecimal
用于需要高精度的地方;例如,财务或货币计算。 BigDecimal
值的算术运算是通过 add
或 subtract
等方法完成的; +
、-
、*
、\ 运算符没有超载。
以下示例显示了使用 BigDecimal
的基本算术运算。
package com.cundage; import java.math.BigDecimal; import java.math.RoundingMode; public class BigDecimalEx { public static void main(String[] args) { var val1 = new BigDecimal("3.44"); var val2 = new BigDecimal("2.74"); BigDecimal res1 = val1.add(val2); System.out.println(res1); BigDecimal res2 = val1.subtract(val2); System.out.println(res2); BigDecimal res3 = val1.multiply(val2); System.out.println(res3); BigDecimal res4 = val1.divide(BigDecimal.TEN, RoundingMode.DOWN); System.out.println(res4); BigDecimal res5 = val1.divide(val2, 15, RoundingMode.HALF_UP); System.out.println(res5); } }
在示例中,我们有加法、减法、乘法和除法运算。
var val1 = new BigDecimal("3.44"); var val2 = new BigDecimal("2.74");
我们创建两个 BigDecimal
值。数字作为字符串传递。
BigDecimal res1 = val1.add(val2); System.out.println(res1);
这里我们添加两个 BigDecimal
数字。添加操作是使用 add
方法执行的。
BigDecimal res4 = val1.divide(BigDecimal.TEN, RoundingMode.DOWN); System.out.println(res4);
在做除法运算时,我们还需要指定舍入方式。
$ java BigDecimalEx.java 6.18 0.70 9.4256 0.34 1.255474452554745
BigDecimal
用于高精度运算。
package com.cundage; import java.math.BigDecimal; public class BigDecimalEx2 { public static void main(String[] args) { double a = 0.1 + 0.1 + 0.1; double b = 0.3; System.out.println(a); System.out.println(b); System.out.println(a == b); var c = new BigDecimal("0.1").add(new BigDecimal("0.1")) .add(new BigDecimal("0.1")); var d = new BigDecimal("0.3"); System.out.println(c); System.out.println(d); System.out.println(c.equals(d)); } }
在示例中,我们将 double
类型的精度与 BigDecimal
的精度进行比较。我们添加三个浮点值并将其与预期输出进行比较。
$ java BigDecimalEx2.java 0.30000000000000004 0.3 false 0.3 0.3 true
double
有一点误差;因此,操作不精确。 BigDecimal
给出了预期的输出。
BigDecimal
类让用户可以完全控制舍入行为。如果没有指定舍入方式,无法表示准确的结果,则抛出异常。
package com.cundage; import java.math.BigDecimal; import java.math.RoundingMode; public class BigDecimalEx3 { public static void main(String[] args) { var x = new BigDecimal("5.54"); BigDecimal x2 = x.setScale(1, RoundingMode.FLOOR); System.out.println(x2); var y = new BigDecimal("5.94"); BigDecimal y2 = y.setScale(1, RoundingMode.CEILING); System.out.println(y2); } }
在示例中,我们以两种不同的舍入模式对两个值进行舍入。
var x = new BigDecimal("5.54"); BigDecimal x2 = x.setScale(1, RoundingMode.FLOOR);
通过 setScale
方法,我们提供了比例和舍入模式。在我们的例子中,我们使用舍入模式 RoundingMode.FLOOR
将值舍入到小数点后一位,舍入到负无穷大。
$ java BigDecimalEx3.java 5.5 6.0
使用 compareTo
方法,两个值相等但比例不同(如 4.0 和 4.00)的 BigDecimal
对象被视为相等这个方法。
package com.cundage; import java.math.BigDecimal; public class BigDecimalEx4 { public static void main(String[] args) { var x = new BigDecimal("1.6"); var y = new BigDecimal("1.60"); System.out.println(x.equals(y)); System.out.println(x.compareTo(y)); } }
该示例将值 1.6 和 1.60 与 equals
和 compareTo
进行比较。
$ java BigDecimalEx4.java false 0
compareTo
为相等的值返回 0。
以下示例按类别对产品进行分组,并计算类别中所有产品的总价。
package com.cundage; import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class BigDecimalEx5 { record Product(String name, String category, BigDecimal price) {} public static void main(String[] args) { Map<String, Map<BigDecimal, List<Product>>> productsByCategories = products().stream().collect( Collectors.groupingBy(Product::category, Collectors.groupingBy(Product::price))); productsByCategories.forEach((k, v) -> { System.out.printf("%s: ", k); var sum = new BigDecimal("0"); var prices = v.keySet(); for (var price: prices) { sum = sum.add(price); } System.out.println(sum); }); } private static List<Product> products() { return List.of( new Product("apple", "fruit", new BigDecimal("4.50")), new Product("banana", "fruit", new BigDecimal("3.76")), new Product("carrot", "vegetables", new BigDecimal("2.98")), new Product("potato", "vegetables", new BigDecimal("0.92")), new Product("garlic", "vegetables", new BigDecimal("1.32")), new Product("ginger", "vegetables", new BigDecimal("2.45")), new Product("white bread", "bakery", new BigDecimal("1.50")), new Product("roll", "bakery", new BigDecimal("0.08")), new Product("bagel", "bakery", new BigDecimal("0.15")) ); } }
我们有三类各种杂货:水果、蔬菜和面包店。我们的目标是按类别对产品进行分组,并计算各个类别中所有价格的总和。
Map<String, Map<BigDecimal, List<Product>>> productsByCategories = products().stream().collect( Collectors.groupingBy(Product::category, Collectors.groupingBy(Product::price)));
使用 Java 流,我们按类别和价格对产品进行分组。
productsByCategories.forEach((k, v) -> { System.out.printf("%s: ", k); var sum = new BigDecimal("0"); var prices = v.keySet(); for (var price: prices) { sum = sum.add(price); } System.out.println(sum); });
在 forEach
循环中,我们计算每个类别的所有价格的总和。
$ java BigDecimalEx5.java bakery: 1.73 fruit: 8.26 vegetables: 7.67
在本文中,我们展示了如何使用 BigDecimal
在 Java 中进行高精度算术运算。
地址:https://www.cundage.com/article/java-bigdecimal.html