Java BigDecimal - 使用 BigDecimal 在 Java 中进行高精度计算

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(430)   2023-06-26 07:54:18

Java BigDecimal 教程展示了如何使用 BigDecimal 在 Java 中执行高精度计算。

什么是BigDecimal

BigDecimal 表示一个不可变的、任意精度的带符号十进制数。用于高精度运算。 BigDecimal 提供算术运算、缩放操作、舍入、比较、散列和格式转换操作。

BigDecimal 由两部分组成:

  • 未缩放的值——任意精度整数
  • scale——一个 32 位整数,表示小数点右边的位数

例如,BigDecimal 2.18 的未缩放值为 218,小数位数为 2。

BigDecimal用于需要高精度的地方;例如,财务或货币计算。 BigDecimal 值的算术运算是通过 addsubtract 等方法完成的; +-*\ 运算符没有超载。

Java BigDecimal 基本算术运算

以下示例显示了使用 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

Java BigDecimal 精度

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 给出了预期的输出。

Java 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

Java BigDecimal 比较

使用 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 与 equalscompareTo 进行比较。

$ java BigDecimalEx4.java
false
0

compareTo 为相等的值返回 0。

Java BigDecimal 实例

以下示例按类别对产品进行分组,并计算类别中所有产品的总价。

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

相关阅读

Spring Boot Vue.js 教程展示了如何使用 Vue.js 框架创建一个简单的 Spring Boot。 Vue.js Vue.js 是一个用于构建用户界面的 JavaScript ...
JavaScript 是否已经取代 Java 成为新的“一次编写,随处运行”的编程语言?这完全取决于您的观点。随着 WebAssembly 等技术的出现,Java 可以在新奇的“一次编写,随处编...
Usage of TypeScript,微软基于 JavaScript 的强类型语言, has soared compared to six years ago, according to th...
云莓将基于 Spring 构建的 Java 后端与使用 Lit 构建的 TypeScript 前端相结合,一个快速、响应式的 JavaScript 框架。基于 Vaadin Fusion 的 H...
本博客严重偏向于 GWT(和基于 GWT 的框架),但我们牢记 GWT 将来可能会被其他技术接管,因此我们始终对探索其他平台/框架持开放态度。正如他们所说,多元化可以降低风险。每种编程语言,即使...
Java JSON 教程展示了如何使用 JSON-Java 在 Java 中进行 JSON 序列化和反序列化。 JSON(JavaScript 对象显示法) 是一种轻量级数据交换格式。人类易于读...
JHipster 是一个长期存在且雄心勃勃的混合 Java 和 JavaScript 项目,致力于使用现代反应式前端简化全栈 Java 应用程序的开发。 JHipster 开发团队不断发布新版本...
解析器是强大的工具,使用 ANTLR 可以编写可用于多种不同语言的各种解析器。 在这个完整的教程中,我们将: 解释基础:什么是解析器,它可以用来做什么 查看如何设置 ANTLR 以便在 Java...
根据最近一项全球开发人员调查,在开发人员偏好方面,JavaScript 和 Python 保持了持久力,而 锈 的使用率正在上升. 5 月 4 日的一份题为“开发者国家情况,第 22nd 版”的...
Spring Boot JSON 教程展示了如何在 Spring Boot 注释中提供 JSON 数据。 春天 是一个流行的 Java 应用程序框架,弹簧贴 是 Spring 的演变,有助于创建...