解决double的值相加的问题

针对double类型的计算的问题之一:

public class DoubleCaculator {
    double price = 0.38;
    int count = 3;
    
    @Test
    public void demo1() {
        //结果:1.1400000000000001
        System.out.println(price * count);
    }
}
    @Test
    public void demo2() {
        //bigDecimal的字符串的构造完美解决了double计算的问题
        BigDecimal bdP = new BigDecimal(price);
        BigDecimal bdc = new BigDecimal(count);
        BigDecimal add = bdP.multiply(bdc);
        System.out.println(add.doubleValue());
    }

此结果是:2.2800000000000002

从上面两个的结果,显然与我们想要的结果有点不一样,如果是针对金融方面的话,那么一个小数点的问题就会影响很大,那么对于这样的问题,我们要如何的解决哪?

答:BigDecimal这个类。

那为啥上面使用了这个BigDecimal为啥还会出现这个问题?

答:传入的参数有问题。

源码的注释说明:如果B中传入的为double类型的值时的解释

The results of this constructor can be somewhat unpredictable.
     * One might assume that writing {@code new BigDecimal(0.1)} in
     * Java creates a {@code BigDecimal} which is exactly equal to
     * 0.1 (an unscaled value of 1, with a scale of 1), but it is
     * actually equal to
     * 0.1000000000000000055511151231257827021181583404541015625.
     * This is because 0.1 cannot be represented exactly as a
     * {@code double} (or, for that matter, as a binary fraction of
     * any finite length).  Thus, the value that is being passed
     * <i>in</i> to the constructor is not exactly equal to 0.1,
     * appearances notwithstanding.
     *

以及给出的最佳的解决方法:

The {@code String} constructor, on the other hand, is
     * perfectly predictable: writing {@code new BigDecimal("0.1")}
     * creates a {@code BigDecimal} which is <i>exactly</i> equal to
     * 0.1, as one would expect.  Therefore, it is generally
     * recommended that the {@linkplain #BigDecimal(String)
     * <tt>String</tt> constructor} be used in preference to this one.
     *

所以上面的代码如果将传入的double类型的值转换成字符串的话,那么问题就解决了:

    @Test
    public void demo2() {
        //bigDecimal的字符串的构造完美解决了double计算的问题
        BigDecimal bdP = new BigDecimal(price + "");
        BigDecimal bdc = new BigDecimal(count + "");
        BigDecimal add = bdP.multiply(bdc);
        System.out.println(add.doubleValue());
    }

 

转载于:https://www.cnblogs.com/donghaibin/p/9338849.html

在程序中,两个double类型相加出现误差的主要原因是浮点数的内部表示方式和精度问题。浮点数在计算机中使用二进制来表示,但有些十进制数无法精确地表示为有限位数的二进制表示,因此会引发舍入误差。 要解决这个问题,我们可以采取以下几个方法: 1. 使用BigDecimal类:BigDecimal类可以提供高精度的十进制运算,可以避免浮点数运算中的舍入误差。可以先将两个double数转换为BigDecimal对象,然后使用add方法进行相加。 2. 当需要比较两个浮点数是否相等时,可以采用比较它们的差小于某个极小的方法,而不是直接比较它们是否完全相等。例如,可以定义一个极小epsilon,并判断Math.abs(a - b) < epsilon来比较。 3. 将浮点数转换为整数进行计算。可以将两个double数乘以一个合适的倍数(如10000),然后将其转换为整数进行相加操作。最后再将结果除以相同的倍数,得到精确的结果。 4. 在使用浮点数的时候,应尽量避免累加操作。因为每次累加都会引入额外的舍入误差。可以尽量减少累加操作,并在必要时使用中间变量来存储结果,以避免精度损失。 综上所述,避免浮点数运算误差的方法包括使用BigDecimal类、比较差、转换为整数运算以及避免累加操作等。在实际编程中,我们需要根据具体情况选择最适合的方法来解决浮点数误差问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值