Java基础快速入门:BigDecimal与Integer包装类

本文纲要

1 ) BigDecimal高精度计算

  1. 为什么需要BigDecimal
  2. BigDecimal的构造方法
  3. 四则运算
  4. 除法与舍入模式

2 ) 基本数据类型包装类——Integer

  1. 包装类概述
  2. Integer对象的创建
  3. 自动装箱与自动拆箱
  4. 类型转换:intString互转
  5. 案例:字符串数字解析

BigDecimal 高精度计算

项目模块结构

mybigdecimal/
├── MyBigDecimalDemo.java        // 初始精度丢失演示 
├── MyBigDecimalDemo2.java       // 构造方法演示 
├── MyBigDecimalDemo3.java       // 四则运算(精确计算)
└── MyBigDecimalDemo4.java       // 除法舍入模式演示 

1 ) 为什么需要BigDecimal

在 Java 中直接对小数进行运算可能会出现精度丢失的问题。例如输出 10.0 / 3.0 的结果,并不是我们期望的无限循环小数 3.333...,而是一个带有额外位数的结果。这是因为计算机底层会将十进制小数转换为二进制进行计算,再转回十进制,这种转换过程对于小数会引入微小的误差。虽然误差很小,但在金融、证券等对精度要求极高的场景中是不可接受的。BigDecimal 类正是为解决这类问题而存在。

package com.wb.demo;
 
public class MyBigDecimalDemo {
    public static void main(String[] args) {
        System.out.println(10.0 / 3.0);  // 输出可能为 3.3333333333333335 
    }
}

2 ) BigDecimal的构造方法

创建 BigDecimal 对象时,建议使用参数为字符串的构造方法,以避免 double 数值本身带来的精度问题。直接传入 double 值(如 new BigDecimal(10.0))会保留底层的二进制误差,而传入字符串则能精确表示。

package com.wb.demo;
 
import java.math.BigDecimal;
 
public class MyBigDecimalDemo2 {
    public static void main(String[] args) {
        BigDecimal bd1 = new BigDecimal(10.0);      // double构造 
        BigDecimal bd2 = new BigDecimal("0.3");     // String构造 
 
        System.out.println(bd1);  // 输出 10 
        System.out.println(bd2);  // 输出 0.3 
    }
}

从输出可以看到,对于整数部分 10.0BigDecimal 会自动去除末尾的零,直接显示 10

3 ) 四则运算

BigDecimal 的加减乘除运算必须通过调用方法来完成,不能直接使用运算符。
方法分别为:

  • add(BigDecimal augend) → 加法
  • subtract(BigDecimal subtrahend) → 减法
  • multiply(BigDecimal multiplicand) → 乘法
  • divide(BigDecimal divisor) → 除法

重要提示:为了保证精确运算,必须使用字符串构造创建 BigDecimal 对象。若使用 double 构造,结果依然会包含误差。

package com.wb.demo;
 
import java.math.BigDecimal;
 
public class MyBigDecimalDemo3 {
    //如果想要进行精确运算,那么请使用字符串的构造 
    public static void main(String[] args) {
        // 错误示范:使用double构造依然不精确 
//        BigDecimal bd1 = new BigDecimal(0.1);
//        BigDecimal bd2 = new BigDecimal(0.2);
//        System.out.println(0.1 + 0.2);  // 0.30000000000000004 
 
        BigDecimal bd1 = new BigDecimal("0.1");
        BigDecimal bd2 = new BigDecimal("0.2");
 
        // 加法 
        BigDecimal add = bd1.add(bd2);
        System.out.println("和为" + add);   // 0.3 
 
        // 减法 
        BigDecimal subtract = bd1.subtract(bd2);
        System.out.println("差为" + subtract); // -0.1 
 
        // 乘法 
        BigDecimal multiply = bd1.multiply(bd2);
        System.out.println("积为" + multiply); // 0.02 
 
        // 除法 
        BigDecimal divide = bd1.divide(bd2);
        System.out.println("商为" + divide);   // 0.5 
    }
}

4 ) 除法与舍入模式

当两个数除不尽时,直接调用 divide(BigDecimal divisor) 会抛出 ArithmeticException,因为 BigDecimal 不知道如何处理无限小数。

此时必须使用重载的 divide 方法,指定保留的小数位数和舍入模式。

方法签名:public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

  • divisor:另一个 BigDecimal 对象
  • scale:小数点后精确到多少位
  • roundingMode:舍入模式,常用的常量有:
  • BigDecimal.ROUND_UP → 进一法(向上取)
  • BigDecimal.ROUND_FLOOR → 去尾法(向下取)
  • BigDecimal.ROUNDHALFUP → 四舍五入
package com.wb.demo;
 
import java.math.BigDecimal;
 
public class MyBigDecimalDemo4 {
    public static void main(String[] args) {
        BigDecimal bd1 = new BigDecimal("0.3");
        BigDecimal bd2 = new BigDecimal("4");  // 0.3 / 4 = 0.075 
 
        // 不带舍入模式的除法——当除不尽时会抛出异常,此处会报错 
        /* BigDecimal divide = bd1.divide(bd2);
           System.out.println(divide); */
 
        // 参数一:参与运算的另一个对象 
        // 参数二:表示小数点后精确到多少位 
        // 参数三:舍入模式 
        //     进一法  BigDecimal.ROUND_UP 
        //     去尾法  BigDecimal.ROUND_FLOOR 
        //     四舍五入 BigDecimal.ROUNDHALFUP 
        BigDecimal divide = bd1.divide(bd2, 2, BigDecimal.ROUNDHALFUP);
        System.out.println(divide);  // 输出 0.08 
    }
}

若换用 BigDecimal.ROUND_FLOOR,输出为 0.07
若换用 BigDecimal.ROUND_UP,输出为 0.08

基本数据类型包装类——Integer

项目模块结构

myinteger/
├── MyIntegerDemo1.java          // Integer常量获取int范围 
├── MyIntegerDemo2.java          // 获取Integer对象(过时构造与valueOf)
├── MyIntegerDemo3.java          // 自动装箱拆箱 
├── MyIntegerDemo4.java          // 类型转换 
└── MyIntegerDemo5.java          // 字符串数字解析案例 

1 ) 包装类概述

Java 为 8 种基本数据类型提供了对应的包装类,目的是将基本类型包装成对象,从而可以在对象中定义各种操作数据的方法。

常见的包装类及对应关系如下:

  • byteByte
  • shortShort
  • intInteger
  • longLong
  • floatFloat
  • doubleDouble
  • charCharacter
  • booleanBoolean

大多数包装类只需将基本类型首字母大写,但 intchar 较为特殊,分别是 IntegerCharacter

例如,通过 Integer 类可以直接获取 int 类型的最大值和最小值:

package com.wb.myinteger;
 
public class MyIntegerDemo1 {
    public static void main(String[] args) {
        //需求:我要判断一个整数是否在 int 范围内?
        System.out.println(Integer.MAX_VALUE);  // 2147483647 
        System.out.println(Integer.MIN_VALUE);  // -2147483648 
    }
}

2 ) Integer对象的创建

创建 Integer 对象有几种方式,早期的构造方法已经过时,推荐使用静态方法 Integer.valueOf(int i)Integer.valueOf(String s)。它们均返回 Integer 实例。

package com.wb.myinteger;
 
public class MyIntegerDemo2 {
    public static void main(String[] args) {
        // 构造方法(均已过时)
        Integer i1 = new Integer(100);
        Integer i2 = new Integer("100");
        System.out.println(i1);  // 100 
        System.out.println(i2);  // 100 
 
        // 静态方法 valueOf(推荐)
        Integer i3 = Integer.valueOf(200);
        Integer i4 = Integer.valueOf("200");
        System.out.println(i3);  // 200 
        System.out.println(i4);  // 200 
    }
}

3 ) 自动装箱与自动拆箱

从 JDK 1.5 开始,Java 提供了自动装箱自动拆箱机制,让基本类型与包装类之间的转换更加简洁。
装箱:将基本数据类型转换为对应的包装类对象。底层自动调用 valueOf 方法。
拆箱:将包装类对象转换为对应的基本数据类型。

示例代码及解读:

package com.wb.myinteger;
 
public class MyIntegerDemo3 {
    public static void main(String[] args) {
        // 自动装箱:int → Integer 
        Integer i1 = 100;          // 底层执行 Integer i1 = Integer.valueOf(100);
        System.out.println(i1);
 
        // 自动拆箱:Integer → int 
        int i2 = i1;               // 底层执行 int i2 = i1.intValue();
        System.out.println(i2);
 
        // 综合案例 
        Integer i3 = 100;          // 自动装箱 
        i3 += 200;                 // 等价于 i3 = i3 + 200;
        // 过程:
        //   1) i3 自动拆箱为 int 值 100 
        //   2) 100 + 200 = 300 
        //   3) 将 int 300 自动装箱为 Integer 对象赋值给 i3 
        System.out.println(i3);   // 300 
 
        // 细节:若包装类对象为 null,拆箱时会抛出 NullPointerException 
        Integer i4 = null;
        if (i4 != null) {
            i4 += 200;
            System.out.println(i4);
        }
        // 如果 i4 为 null,执行 i4 += 200 会引发 NullPointerException,
        // 因此建议在使用前做非空判断。
    }
}

4 ) 类型转换:intString互转

在实际开发中,经常需要将字符串数字转换为 int 参与计算,或将 int 转换为字符串进行拼接或展示。

String → int:使用 Integer.parseInt(String s) 静态方法。

String s1 = "100";
int i1 = 200;
int i2 = Integer.parseInt(s1);   // 将字符串 "100" 转为 int 100 
System.out.println(i2 + i1);     // 300,而不是 "100200"

int → String:两种常用方式。

int i3 = 100;
// 方式一:拼接空字符串 
String s2 = i3 + "";
System.out.println(s2 + 100);   // 100100(字符串操作)
 
// 方式二:使用 String.valueOf(int)
String s3 = String.valueOf(i3);
System.out.println(s3 + 100);   // 100100 

完整演示:

package com.wb.myinteger;
 
public class MyIntegerDemo4 {
    public static void main(String[] args) {
        // String 转 int 
        String s1 = "100";
        int i1 = 200;
        System.out.println(s1 + i1);            // 100200 —— 字符串拼接 
        int i2 = Integer.parseInt(s1);
        System.out.println(i2 + i1);            // 300 —— 整数加法 
 
        // int 转 String 
        int i3 = 100;
        String s2 = i3 + "";                    // 方式一 
        System.out.println(s2 + 100);          // 100100 
        String s3 = String.valueOf(i3);         // 方式二 
        System.out.println(s3 + 100);          // 100100 
    }
}

5 ) 案例:字符串数字解析

需求:将字符串 "91 27 46 38 50" 中的每个数字提取出来,存入 int 数组并遍历输出。

解题步骤:

  1. 将字符串按空格分割为字符串数组;
  2. 创建等长的 int 数组;
  3. 遍历字符串数组,使用 Integer.parseInt() 转换并存储;
  4. 遍历 int 数组输出结果。
package com.wb.myinteger;
 
public class MyIntegerDemo5 {
    //需求:有一个字符串:“91 27 46 38 50”,把其中的每一个数存到int类型的数组中 
    public static void main(String[] args) {
        String s = "91 27 46 38 50";
        // 1. 获取字符串中的每一个数字,按空格切割 
        String[] strArr = s.split(" ");
 
        // 2. 创建一个等长的int类型数组 
        int[] numberArr = new int[strArr.length];
 
        // 3. 把strArr中的数据进行类型转换并存入int数组 
        for (int i = 0; i < strArr.length; i++) {
            int number = Integer.parseInt(strArr[i]);
            numberArr[i] = number;
        }
 
        // 4. 遍历int类型的数组并输出 
        for (int i = 0; i < numberArr.length; i++) {
            System.out.println(numberArr[i]);
        }
    }
}

运行结果将依次打印:9127463850

总结

以上内容涵盖了 BigDecimal 高精度计算以及 Integer 包装类的核心用法,配合示例代码可以帮助快速上手

后续可在此基础上进一步学习其他包装类及 BigDecimal 更高级的舍入策略等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值