BigDecimal 使用的坑

new BigDecimal 构造函数可以接收 double 或 String 类型的参数来创建 BigDecimal 对象,区别如下:
使用 double 类型:可能会导致精度丢失,因为 double 不能精确表示所有十进制数。
使用 String 类型:能够精确表示数值,避免 double 类型的精度问题,推荐用于需要高精度计算的场景。
 

当使用 double 类型作为 BigDecimal 的构造函数参数时,可能会发生精度丢失,原因在于 double 类型本身的设计。double 是基于 IEEE 754 标准的二进制浮点数格式存储数值,它使用了64位来表示一个数字,其中包含了1位符号位、11位指数位和52位尾数位。
由于二进制浮点数是用有限长度的二进制来表示数值,不是所有的十进制小数都能被精确地表示为二进制形式。例如,十进制中的0.1在二进制中是一个无限循环小数(0.0001100110011...),这就导致了在转换过程中会出现精度上的损失。
当这种不精确的 double 值被传递给 BigDecimal 构造函数时,BigDecimal 会根据 double 的内部二进制表示来创建其值,从而引入了原本不应该存在的误差。
为了避免这种情况,通常建议直接使用字符串(如 String)来初始化 BigDecimal,这样可以确保数值被准确无误地解析,不会引入额外的精度损失。

在二进制中,某些十进制小数无法被精确表示,会变成无限不循环小数。具体来说,以下类型的十进制小数在二进制中无法精确表示:
含有 2 以外的质因数的分母:
十进制中的分数形式,如果分母(以 10 为底的)含有除 2 和 5 之外的质因数,则在二进制中无法精确表示。
例如,0.1(即 1/10)在二进制中是一个无限循环小数(0.0001100110011...)。
特定的小数形式:
一些常见的例子包括 0.1、0.2、0.3 等。
例如,0.1 在二进制中表示为 0.0001100110011...,无法精确表示。
具体示例:
0.1:在二进制中表示为 0.0001100110011...(无限循环)
0.2:在二进制中表示为 0.001100110011...(无限循环)
0.3:在二进制中表示为 0.01001100110011...(无限循环)
这些数值在二进制中无法用有限位数精确表示,因此在计算机中使用 double 类型存储时会产生精度损失。为了保证精度,建议使用 String 类型初始化 BigDecimal。


除了之前提到的例子,其他一些十进制小数在二进制中也会成为无限循环或无限不循环小数。具体来说,任何不能被2的幂次整除的分数形式的十进制小数,在二进制中都会变成无限循环或无限不循环小数。以下是一些额外的例子:
0.4 (2/5):在二进制中表示为 0.01100110011...(无限循环)
0.5 (1/2):在二进制中表示为 0.1(有限小数)
0.6 (3/5):在二进制中表示为 0.100110011...(无限循环)
0.7 (7/10):在二进制中表示为 0.101100110011...(无限循环)
0.8 (4/5):在二进制中表示为 0.1100110011...(无限循环)
可以看到,只要分母含有除2以外的质因数,那么该分数形式的小数在二进制中就无法被精确表示。只有那些分母仅含有2的幂次的分数形式的小数,在二进制中才是有限小数。例如,0.5(1/2)、0.25(1/4)、0.125(1/8)等都是可以在二进制中精确表示的有限小数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值