我是靠谱客的博主 如意方盒,最近开发中收集的这篇文章主要介绍BigDecimal类中的double类型值的加减问题-java,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

了解到BigInteger类可以存入无限大小的值,从而可以用它进行大数值计算.
BigInteger中的构造方法中的一个参数是没有可以直接接受int,double,等基本数据类型,一个参数是接受String类型.
但是,BigDecimal类是可以接受double,int,long,String类型的值.问题就由此出现了.


问题:

import java.math.BigDecimal;

public class BigDecimalDemo {
	public static void main(String[] args) {
		System.out.println(1.1+1.2101);
		BigDecimal bd1 = new BigDecimal(1.1);
		BigDecimal bd2 = new BigDecimal(1.2101);
		System.out.println(bd1.add(bd2));
	}
}
/*输出:
2.3101000000000003
2.3101000000000000422772927777259610593318939208984375
*/

BigDecimal(摘自Java SE8 API文档)

public BigDecimal(double val)Translates a double into a BigDecimal which is the exact decimal representation of the double’s binary floating-point value. The scale of the returned BigDecimal is the smallest value such that (10scale × val) is an integer.

Notes:
  1.The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a 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 double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
  2.The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal(“0.1”) creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.
  3.When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.

Parameters:
val - double value to be converted to BigDecimal.

Throws:
NumberFormatException - if val is infinite or NaN.

 文档中说的很明白,对于Decimal中double构造器,该构造器的结果可能有些不可预料.这是因为0.1不能精确地表示为双精度(或者,就此而言,不能表示为任何有限长度的二进制分式)。因此,传递给构造函数的值并不完全等于0.1,尽管看起来是这样。
 推荐使用String构造器,它与所存的double类型的字符串所预料的是一样的.
 可以看看这篇文章:浮点数存储.


解决办法:

import java.math.BigDecimal;

public class BigDecimalDemo {
	public static void main(String[] args) {
		bd1 = new BigDecimal("1.1");
		bd2 = new BigDecimal("1.2101");
		System.out.println(bd1.add(bd2));
		System.out.println(BigDecimal.valueOf(1.1).add(BigDecimal.valueOf(1.2101)));
	}
}
/*输出:
2.3101
2.3101
*/
  1. 使用BigDecimal(String val)构造器


  2. 先将double类型的值使用public static BigDecimal valueOf(double val)方法.
    原理:将double类型的值先转换为String类型的值,在存储到BigDecimal对象中.

BigDecimal.valueOf(double val)源码:

 public static BigDecimal valueOf(double val) {
       // Reminder: a zero double returns '0.0', so we cannot fastpath
       // to use the constant ZERO.  This might be important enough to
       // justify a factory approach, a cache, or a few private
       // constants, later.
       return new BigDecimal(Double.toString(val));
   }

API中0.1 (an unscaled value of 1, with a scale of 1)的理解

API文档中有一句(an unscaled value of 1, with a scale of 1)该如何理解呢?

BigDecimal类中有unscaledValue()scale()方法.通过这两个方法来理解这句话吧.

unscaledValue

public BigInteger unscaledValue()
Returns a BigInteger whose value is the unscaled value of this BigDecimal. (Computes (this * 10this.scale()).)

Returns:
the unscaled value of this BigDecimal.

Since:
1.2

scale

public int scale()
Returns the scale of this BigDecimal. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. For example, a scale of -3 means the unscaled value is multiplied by 1000.

Returns:
the scale of this BigDecimal.

方法应用

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;

public class FoctorialDemo {
	public static void main(String[] args) {
		BigDecimal bd = new BigDecimal("-1.2101");	
		System.out.println(bd.scale());
		System.out.println(bd.unscaledValue());
	}
}
/*输出:
4
-12101
*/

通过输出可以了解到scale()方法是返回该BigDecimal的值的小数位数.scale这个单词有数值范围的意思.
         unscaledValue()方法是将BigInteger的值去除小数点.也就相当于
t h i s ∗ 1 0 t h i s . s c a l e ( ) this*10^{this.scale()} this10this.scale()

0.1 (an unscaled value of 1, with a scale of 1)这句话也就好理解了.去掉小数点即为1;小数点的数值范围为1.

最后

以上就是如意方盒为你收集整理的BigDecimal类中的double类型值的加减问题-java的全部内容,希望文章能够帮你解决BigDecimal类中的double类型值的加减问题-java所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部