欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 【Java基础面试题043】BigDecimal为什么能保证精度不丢失?

【Java基础面试题043】BigDecimal为什么能保证精度不丢失?

2025/4/19 0:56:57 来源:https://blog.csdn.net/lklalmq/article/details/144706756  浏览:    关键词:【Java基础面试题043】BigDecimal为什么能保证精度不丢失?

回答重点

BigDecimal使用十进制来表示数值,而不是二进制浮点数表示法,这使得它能够精确地表示所有十进制数值,不需要任何转换或舍入。

而且BigDecimal是无限精度,可以表示任意精度的小数(受限于内存),因此不会动不动被舍入截断,也可以手动设置精度和舍入模式来控制计算的精度

BigDecimal内部使用两个字段存储数字,一个是整数部分intVal,另一个用来表示小数点的位置scale,避免了浮点数转化过程中可能的精度丢失

计算时通过整数计算,再结合小数点位置和设置的精度与舍入行为,控制结果精度,避免了有默认浮点数舍入导致的误差

简化版:

public class BigDecimal extends Number implements Comparable<BigDecimal> {private final BigInteger intVal;  // 存储整数部分private final int scale;          // 存储小数点的位置public BigDecimal(String val) {// 使用 BigInteger 来表示数值intVal = new BigInteger(val.replace(".", ""));scale = val.contains(".") ? val.length() - val.indexOf(".") - 1 : 0;}
}

例如:

BigDecimal bigDecimal = new BigDecimal(11.123);

inVal存储11122999999999332 ...

scale存储49,因为小数后有49位

如果是另外两种创建对象的方式,经过断点调试,inVal的值是null,scale是3

扩展知识

浮点数精度丢失的原因

  • 二进制浮点数表示:
    • Java使用IEEE 754标准来表示浮点数,这个标准用二进制来表示小数
    • 但有些十进制小数在二进制下是无限不循环小数(例如0.1在二进制中是0.0001100110011...),因此需要被截断或四舍五入
  • 有限的表示范围:
    • floatdouble都有固定的大小(float是32位,double是64位),这限制了它们能表示的精度和范围。有些数字在这些有限的位数内无法精确表示。
  • 舍入误差:
    • 由于浮点数的表示方式,进行算术运算时,可能会产生舍入误差。例如,0.1 + 0.2在理论上应该等于0.3,但在浮点数运算中可能得到0.30000000000000004

0.1 * 0.2

public class FloatPrecisionExample {public static void main(String[] args) {double a = 0.1;double b = 0.2;System.out.println(a * b); // 输出 0.020000000000000004}
}

由于double底层是二进制来表示十进制小数,不过double并不能精确表示0.1,0.2,所以0.1 * 0.2自然就产生了微笑的误差

使用BigDecimal

import java.math.BigDecimal;public class BigDecimalPrecisionExample {public static void main(String[] args) {BigDecimal a = new BigDecimal("0.1");BigDecimal b = new BigDecimal("0.2");System.out.println(a.multiply(b));  // 输出 0.02}
}

0.1 * 0.2底层大概是这么处理的:

0.1:intVal = 1        scale = 1

0.2:intVal = 2        scale = 1

先1 x 2 = 2

再标小数点位置2 -> 0.02

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词