针对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()); }