BigDecimal 小数 浮点数 精度 财务计算

最常用法示例

构造方法

//测试构造方法
System.out.println("double类型的1.22:" + new BigDecimal(1.22));//1.2199999999999999733546474089962430298328399658203125
System.out.println("String类型的1.22: " + new BigDecimal("1.22"));//1.22
System.out.println("double类型的1.22:" + new BigDecimal(Double.toString(1.22)));//1.22

System.out.println("double类型的1.22:" + new BigDecimal(1.22).doubleValue());//1.22
System.out.println("String类型的1.22: " + new BigDecimal("1.22").doubleValue());//1.22

加减乘除运算

//测试加法
double addValue = BigDecimal.valueOf(0.05).add(BigDecimal.valueOf(0.01)).doubleValue();
System.out.println("0.05+0.01=" + (0.05 + 0.01) + "  " + addValue);//0.05+0.01=0.060000000000000005  0.06
//测试减法
double subtractValue = BigDecimal.valueOf(1.0).subtract(BigDecimal.valueOf(0.42)).doubleValue();
System.out.println("1.0-0.42=" + (1.0 - 0.42) + "  " + subtractValue);//1.0-0.42=0.5800000000000001  0.58
//测试乘法
double multiplyValue = BigDecimal.valueOf(4.015).multiply(BigDecimal.valueOf(100)).doubleValue();
System.out.println("4.015*100=" + (4.015 * 100) + "  " + multiplyValue);//4.015*100=401.49999999999994  401.5
//测试除法
double divideValue = BigDecimal.valueOf(123.3).divide(BigDecimal.valueOf(100), 10, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println("123.3/100=" + (123.3 / 100) + "  " + divideValue);//123.3/100=1.2329999999999999  1.233

BigDecimal简介

借用《Effactive Java》这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合。但是,商业计算往往要求结果精确,这时候BigDecimal就派上大用场啦。

BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负scale 次幂。因此,BigDecimal表示的数值是(unscaledValue * 10^-scale)。

当 double 必须用作 BigDecimal 的源时,可使用下面两种方式之一:

1、直接使用静态的valueOf方法

//这通常是将double和float转换为一个BigDecimal的最好方式
public static BigDecimal valueOf(double val) {
	return new BigDecimal(Double.toString(val));
}

2、先使用Double.toString方法将double转换为String

BigDecimal bigDecimal= new BigDecimal(Double.toString(1.22));

避免使用含有double的构造方法!

总结

  • (1)商业计算使用BigDecimal。
  • (2)尽量使用参数类型为String的构造函数。
  • (3) BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值。
  • (4)我们往往容易忽略JDK底层的一些实现细节,导致出现错误,需要多加注意。

JDK中的介绍

继承关系

public class BigDecimal extends Number implements Comparable<BigDecimal>

不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。因此,BigDecimal 表示的数值是 (unscaledValue × 10^-scale)。

BigDecimal 类提供以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。toString() 方法提供 BigDecimal 的规范表示形式。

BigDecimal 类使用户能完全控制舍入行为。如果未指定舍入模式,并且无法表示准确结果,则抛出一个异常;否则,通过向该操作提供适当的 MathContext 对象,可以对已选择的精度和舍入模式执行计算。在任何情况下,可以为舍入控制提供八种舍入模式。使用此类(例如,ROUND_HALF_UP)中的整数字段来表示舍入模式已过时;应改为使用 RoundingMode enum(例如,RoundingMode.HALF_UP)的枚举值。

当为 MathContext 对象提供 0 的精度设置(例如,MathContext.UNLIMITED)时,算术运算是准确的,它们是不采用任何 MathContext 对象的算术方法。(这是第 5 版之前的版本支持的唯一行为。)为了计算准确结果,不使用附带 0 精度设置的 MathContext 对象的舍入模式设置,因此与该对象无关。在除法中,准确的商可能是一个无限长的十进制扩展;例如,1 除以 3 所得的商。如果商具有无穷的十进制扩展,但是指定了该操作返回准确结果,则抛出 ArithmeticException。否则,像其他操作那样,返回除法运算的准确结果。

当精度设置不为 0 时,BigDecimal 算法的规则完全符合 ANSI X3.274-1996 和 ANSI X3.274-1996/AM 1-2000( 7.4 节)中定义的算法的可选操作模式。与上述标准不同,BigDecimal 包括多种舍入模式,它们对于版本 5 以前的 BigDecimal 版本中的除法是强制性的。这些 ANSI 标准和 BigDecimal 规范之间的任何冲突都按照有利于 BigDecimal 的方式进行解决。

由于同一数值可以有不同的表示形式(具有不同的标度),因此运算和舍入的规则必须同时指定数值结果和结果表示形式中所用的标度。

一般情况下,当准确结果(在除法中,可能有无限多位)比返回的数值具有更多位数时,舍入模式和精度设置确定操作如何返回具有有限位数的结果。 首先,MathContext 的 precision 设置指定要返回的总位数;这确定了结果的精度。位数计数从准确结果的最左边的非零数字开始。舍入模式确定丢弃的尾部位数如何影响返回的结果。

对于所有算术运算符,运算的执行方式是,首先计算准确的中间结果,然后,使用选择的舍入模式将其舍入为精度设置(如有必要)指定的位数。如果不返回准确结果,则将丢弃准确结果的某些数位。当舍入增加了返回结果的大小时,前导数字“9”的进位传播可能会创建新的数位。例如,将值 999.9 舍入为三位数字,则在数值上等于一千,表示为 100×10^1。在这种情况下,新的 "1" 是返回结果的前导数位。

除了逻辑的准确结果外,每种算术运算都有一个表示结果的首选标度。下表列出了每个运算的首选标度。

算术运算结果的首选标度

运算  结果的首选标度
加    max(addend.scale(), augend.scale())
减    max(minuend.scale(), subtrahend.scale())
乘    multiplier.scale() + multiplicand.scale()
除    dividend.scale() - divisor.scale() 

这些标度是返回准确算术结果的方法使用的标度;准确相除可能必须使用较大的标度除外,因为准确的结果可能有较多的位数。例如, 1/32 得到 0.03125。

舍入之前,逻辑的准确中间结果的标度是该运算的首选标度。如果用 precision 位数无法表示准确的数值结果,则舍入会选择要返回的一组数字,并将该结果的标度从中间结果的标度减小到可以表示实际返回的 precision 位数的最小标度。如果准确结果可以使用最多 precision 个数字表示,则返回具有最接近首选标度的标度的结果表示形式。尤其是,通过移除结尾零并减少标度,可以用少于 precision 个数字来表示准确的可表示的商。例如,使用 floor 舍入模式将结果舍入为三个数字,

19/100 = 0.19 // integer=19, scale=2

但是

21/110 = 0.190 // integer=190, scale=3

注意,对于加、减和乘,标度的缩减量将等于丢弃的准确结果的数字位置数。如果舍入导致进位传播创建一个新的高位,则当未创建新的数位时,会丢弃该结果的附加数字。

其他方法可能与舍入语义稍微不同。例如,使用指定的算法的 pow 方法得到的结果可能偶尔不同于舍入得到的算术结果,如最后一位有多个单位(ulp)。

可以通过两种类型的操作来处理 BigDecimal 的标度:标度/舍入操作和小数点移动操作。标度/舍入操作(setScale 和 round)返回 BigDecimal,其值近似地(或精确地)等于操作数的值,但是其标度或精度是指定的值;即:它们会增加或减少对其值具有最小影响的存储数的精度。小数点移动操作(movePointLeft 和 movePointRight)返回从操作数创建的 BigDecimal,创建的方法是按指定方向将小数点移动一个指定距离。

为了简洁明了起见,整个 BigDecimal 方法的描述中都使用了伪代码。伪代码表达式 (i + j) 是“其值为 BigDecimal i 加 BigDecimal j 的 BigDecimal”的简写。伪代码表达式 (i == j) 是“当且仅当 BigDecimal i 表示与 BigDecimal j 相同的值时,则为 true”的简写。可以类似地解释其他伪代码表达式。方括号用于表示特定的 BigInteger 和定义 BigDecimal 值的标度对;例如,[19, 2] 表示 BigDecimal 在数值上等于 0.19,标度是 2。

注:如果 BigDecimal 对象用作 SortedMap 中的键或 SortedSet 中的元素,则应特别小心,因为 BigDecimal 的自然排序与 equals 方法不一致。有关更多信息,请参见 Comparable、SortedMap 或 SortedSet。

当为任何输入参数传递 null 对象引用时,此类的所有方法和构造方法都将抛出 NullPointerException。

静态字段

三个实例

  • static BigDecimal  ONE  值为 1,标度为 0。
  • static BigDecimal  TEN  值为 10,标度为 0。
  • static BigDecimal  ZERO  值为 0,标度为 0。

以下模式和RoundingMode中定义的模式是一致的,详见另一篇笔记。

  1. static int  ROUND_CEILING(天花板; 最高限度)  接近正无穷大的舍入模式。
  2. static int  ROUND_DOWN  接近零的舍入模式。
  3. static int  ROUND_FLOOR  接近负无穷大的舍入模式。
  4. static int  ROUND_UP  舍入远离零的舍入模式。
  5. static int  ROUND_UNNECESSARY  断言请求的操作具有精确的结果,因此不需要舍入。
  6. static int  ROUND_HALF_DOWN  向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。
  7. static int  ROUND_HALF_EVEN  向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
  8. static int  ROUND_HALF_UP  向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。

构造方法

将BigInteger转换为BigDecimal

  • BigDecimal(BigInteger val)  将 BigInteger 转换为 BigDecimal。
  • BigDecimal(BigInteger unscaledVal, int scale)  将 BigInteger 非标度值和 int 标度转换为 BigDecimal。
  • BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)  将 BigInteger 非标度值和 int 标度转换为 BigDecimal(根据上下文设置进行舍入)。
  • BigDecimal(BigInteger val, MathContext mc)  将 BigInteger 转换为 BigDecimal(根据上下文设置进行舍入)。

将char[]转换为BigDecimal

  • BigDecimal(char[] in)  将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列。
  • BigDecimal(char[] in, int offset, int len)  将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列,同时允许指定子数组。
  • BigDecimal(char[] in, int offset, int len, MathContext mc)  将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与
  • BigDecimal(char[] in, MathContext mc)  将 BigDecimal 的字符数组表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符序列(根据上下文设置进行舍入)。

将基本类型转换为BigDecimal

  • BigDecimal(double val)  将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。
  • BigDecimal(double val, MathContext mc)  将 double 转换为 BigDecimal(根据上下文设置进行舍入)。
  • BigDecimal(int val)  将 int 转换为 BigDecimal。
  • BigDecimal(int val, MathContext mc)  将 int 转换为 BigDecimal(根据上下文设置进行舍入)。
  • BigDecimal(long val)  将 long 转换为 BigDecimal。
  • BigDecimal(long val, MathContext mc)  将 long 转换为 BigDecimal(根据上下文设置进行舍入)。
  • BigDecimal(String val)  将 BigDecimal 的字符串表示形式转换为 BigDecimal。
  • BigDecimal(String val, MathContext mc)  将 BigDecimal 的字符串表示形式转换为 BigDecimal,接受与 BigDecimal(String) 构造方法相同的字符串(按照上下文设置进行舍入)。

JDK中对参数类型为double的构造方法的描述:

  • 1、参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。
  • 2、另一方面,String 构造方法是完全可预知的:写入 newBigDecimal("0.1") 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法。
  • 3、当 double 必须用作 BigDecimal 的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用 Double.toString(double) 方法,然后使用 BigDecimal(String) 构造方法,将 double 转换为 String。要获取该结果,请使用 static valueOf(double) 方法。

静态方法:将基本类型转换为BD

  • static BigDecimal  valueOf(double val)  使用 Double.toString(double) 方法提供的 double 规范的字符串表示形式将 double 转换为 BigDecimal。注:这通常是将 double(或 float)转化为 BigDecimal 的首选方法,因为返回的值等于从构造 BigDecimal(使用 Double.toString(double) 得到的结果)得到的值。
  • static BigDecimal  valueOf(long val)  将 long 值转换为具有零标度的 BigDecimal。
  • static BigDecimal  valueOf(long unscaledVal, int scale)  将 long 非标度值和 int 标度转换为 BigDecimal。

普通方法

加减乘除幂

  1. BigDecimal  add(BigDecimal augend)  返回一个 BigDecimal,其值为 (this + augend),其标度为 max(this.scale(), augend.scale())。
  2. BigDecimal  subtract(BigDecimal subtrahend)  返回一个 BigDecimal,其值为 (this - subtrahend),其标度为 max(this.scale(), subtrahend.scale())。
  3. BigDecimal  multiply(BigDecimal multiplicand)  返回一个 BigDecimal,其值为 (this × multiplicand),其标度为 (this.scale() + multiplicand.scale())。
  4. BigDecimal  divide(BigDecimal divisor)  返回一个 BigDecimal,其值为 (this / divisor),其首选标度为 (this.scale() - divisor.scale());如果无法表示准确的商值(因为它有无穷的十进制扩展),则抛出 ArithmeticException。
  5. BigDecimal  pow(int n)  返回其值为 (this^n) 的 BigDecimal,准确计算该幂,使其具有无限精度。参数 n 必须在 0 到 999999999(包括)之间。ZERO.pow(0) 返回 ONE。 注意,未来版本可能会扩展此方法允许的指数范围。
  6. BigDecimal  scaleByPowerOfTen(int n)  返回其数值等于 (this * 10^n) 的 BigDecimal。该结果的标度为 (this.scale() - n)。

【带MathContext参数】

  1. BigDecimal  add(BigDecimal augend, MathContext mc)  返回其值为 (this + augend) 的 BigDecimal(根据上下文设置进行舍入)。
  2. BigDecimal  subtract(BigDecimal subtrahend, MathContext mc)  返回其值为 (this - subtrahend) 的 BigDecimal(根据上下文设置进行舍入)。
  3. BigDecimal  multiply(BigDecimal multiplicand, MathContext mc)  返回其值为 (this × multiplicand) 的 BigDecimal(根据上下文设置进行舍入)。
  4. BigDecimal  divide(BigDecimal divisor, MathContext mc)  返回其值为 (this / divisor) 的 BigDecimal(根据上下文设置进行舍入)。
  5. BigDecimal  pow(int n, MathContext mc)  返回其值为 (thisn) 的 BigDecimal。

除法_扩展

【为除法指定舍入模式】

  • BigDecimal  divide(BigDecimal divisor, int roundingMode)  返回一个 BigDecimal,其值为 (this / divisor),其标度为 this.scale()。如果必须执行舍入,以生成具有给定标度的结果,则应用指定的舍入模式。相对于此遗留方法,应优先使用新的 divide(BigDecimal, RoundingMode) 方法。
  • BigDecimal  divide(BigDecimal divisor, RoundingMode roundingMode)  返回一个 BigDecimal,其值为 (this / divisor),其标度为 this.scale()。

【为除法指定标度和舍入模式】

  • BigDecimal  divide(BigDecimal divisor, int scale, int roundingMode)  返回一个 BigDecimal,其值为 (this / divisor),其标度为指定标度。如果必须执行舍入,以生成具有指定标度的结果,则应用指定的舍入模式。相对于此遗留方法,应优先使用新的 divide(BigDecimal, int, RoundingMode) 方法。
  • BigDecimal  divide(BigDecimal divisor, int scale, RoundingMode roundingMode)  返回一个 BigDecimal,其值为 (this / divisor),其标度为指定标度。如果必须执行舍入,以生成具有指定标度的结果,则应用指定的舍入模式。

取余和取整

  • BigDecimal  remainder(BigDecimal divisor)  返回其值为 (this % divisor) 的 BigDecimal。余数由 this.subtract(this.divideToIntegralValue(divisor).multiply(divisor)) 给出。注意,这不是模操作(结果可以为负)。
  • BigDecimal  divideToIntegralValue(BigDecimal divisor)  返回 BigDecimal,其值为向下舍入所得商值 (this / divisor) 的整数部分。该结果的首选标度为 (this.scale() - divisor.scale())。
  • BigDecimal[]  divideAndRemainder(BigDecimal divisor)  返回由两个元素组成的 BigDecimal 数组,该数组包含 divideToIntegralValue 的结果,后跟对两个操作数计算所得到的 remainder。注意,如果同时需要整数商和余数,则此方法比分别使用 divideToIntegralValue 和 remainder 方法更快速,因为相除仅需执行一次。

【带MathContext参数】

  • BigDecimal  remainder(BigDecimal divisor, MathContext mc)  返回其值为 (this % divisor) 的 BigDecimal(根据上下文设置进行舍入)。
  • BigDecimal  divideToIntegralValue(BigDecimal divisor, MathContext mc)  返回 BigDecimal,其值为 (this / divisor) 的整数部分。
  • BigDecimal[]  divideAndRemainder(BigDecimal divisor, MathContext mc)  返回由两个元素组成的 BigDecimal 数组,该数组包含 divideToIntegralValue 的结果,后跟根据上下文设置对两个操作数进行舍入计算所得到的 remainder 的结果。

绝对值、正负值、近似值

  • BigDecimal  abs()  返回 BigDecimal,其值为此 BigDecimal 的绝对值,其标度为 this.scale()。
  • BigDecimal  negate()  返回 BigDecimal,其值为 (-this),其标度为 this.scale()。
  • BigDecimal  plus()  返回 BigDecimal,其值为 (+this),其标度为 this.scale()。此方法仅返回此 BigDecimal,该方法与一元减方法 negate() 对称

【带MathContext参数】

  • BigDecimal  abs(MathContext mc)  返回其值为此 BigDecimal 绝对值的 BigDecimal(根据上下文设置进行舍入)。
  • BigDecimal  negate(MathContext mc)  返回其值为 (-this) 的 BigDecimal(根据上下文设置进行舍入)。
  • BigDecimal  plus(MathContext mc)  返回其值为 (+this) 的 BigDecimal(根据上下文设置进行舍入)。此方法的效果与 round(MathContext) 方法的效果相同。
  • BigDecimal  round(MathContext mc)  返回根据 MathContext 设置进行舍入后的 BigDecimal。如果精度设置为 0,则不进行任何舍入操作。此方法的效果与 plus(MathContext) 方法的效果相同。

最大最小值

  • BigDecimal  max(BigDecimal val)  返回此 BigDecimal 和 val 的最大值。根据 compareTo 方法的定义,如果它们相等,则返回 this。
  • BigDecimal  min(BigDecimal val)  返回此 BigDecimal 和 val 的最小值。根据 compareTo 方法的定义,如果它们相等,则返回 this。

移动小数点

  • BigDecimal  movePointLeft(int n)  返回一个 BigDecimal,它等效于将该值的小数点向左移动 n 位。如果 n 为非负数,则调用仅将 n 添加到该标度。如果 n 为负数,则该调用等效于 movePointRight(-n)。此调用返回的 BigDecimal 的值为 (this * 10^-n),标度为 max(this.scale()+n, 0)。
  • BigDecimal  movePointRight(int n)  返回一个 BigDecimal,它等效于将该值的小数点向右移动 n 位。如果 n 为非负数,则该调用仅从该标度减去 n。如果 n 为负,则该调用等效于 movePointLeft(-n)。此调用返回的 BigDecimal 的值为 (this * 10^n),标度为 max(this.scale()-n, 0)。

设置标度

  • BigDecimal  setScale(int newScale)  返回一个 BigDecimal,其标度为指定值,其值在数值上等于此 BigDecimal 的值。如果这不可能,则抛出 ArithmeticException。
  • BigDecimal  setScale(int newScale, int roundingMode)  返回一个 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,以维护其总值。相对于此遗留方法,应优先使用新的 setScale(int, RoundingMode) 方法。
  • BigDecimal  setScale(int newScale, RoundingMode roundingMode)  返回 BigDecimal,其标度为指定值,其非标度值通过此 BigDecimal 的非标度值乘以或除以十的适当次幂来确定,以维护其总值。

其他返回BigDecimal的方法

【其他方法】

  • BigDecimal  stripTrailingZeros()  返回数值上等于此小数,但从该表示形式移除所有尾部零的 BigDecimal。
  • BigDecimal  ulp()  返回此 BigDecimal 的 ulp(最后一位的单位)的大小。

转换为基本数据类型

【转换为基本数据类型】

  1. byte  byteValueExact()  将此 BigDecimal 转换为 byte,以检查丢失的信息。如果此 BigDecimal 具有非零小数部分,或者超出 byte 结果的可能范围,则抛出 ArithmeticException。
  2. short  shortValueExact()  将此 BigDecimal 转换为 short,以检查丢失的信息。如果此 BigDecimal 具有非零小数部分,或者超出 short 结果的可能范围,则抛出 ArithmeticException。
  3. int  intValueExact()  将此 BigDecimal 转换为 int,以检查丢失的信息。如果此 BigDecimal 具有非零小数部分,或者超出 int 结果的可能范围,则抛出 ArithmeticException。
  4. long  longValueExact()  将此 BigDecimal 转换为 long,以检查丢失的信息。如果此 BigDecimal 具有非零小数部分,或者超出 long 结果的可能范围,则抛出 ArithmeticException。

【基本收缩转换】

  1. int  intValue()  将此 BigDecimal 转换为 int。此转换类似于 Java Language Specification 中定义的从 double 到 short 的 基本收缩转换:将丢弃此 BigDecimal 的所有小数部分,并且如果生成的 " BigInteger" 太大而不适合用 int 表示,则仅返回 32 位低位字节。注意,此转换会丢失关于此 BigDecimal 值的总大小和精度的信息,并返回带有相反符号的结果。
  2. long  longValue()  将此 BigDecimal 转换为 long。此转换类似于 Java Language Specification 中定义的从 double 到 short 的 基本收缩转换:将丢弃此 BigDecimal 的小数部分,并且如果生成的 " BigInteger" 太大而不适合用 long 表示,则仅返回 64 位低位字节。注意,此转换会丢失关于此 BigDecimal 值的总大小和精度的信息,并返回带有相反符号的结果。
  3. float  floatValue()  将此 BigDecimal 转换为 float。此转换类似于 Java Language Specification 中定义的从 double 到 float 的 基本收缩转换:如此 BigDecimal 的值太大而不能表示为 float,则将其适当地转换为 Float.NEGATIVE_INFINITY 或 Float.POSITIVE_INFINITY。注意,即使在返回值为有限值的情况下,此转换也可能丢失关于 BigDecimal 值精度的信息。
  4. double  doubleValue()  将此 BigDecimal 转换为 double。此转换类似于 Java Language Specification 中定义的从 double 到 float 的 基本收缩转换:如果此 BigDecimal 的数量太大而不能表示为 double,则将其适当地转换为 Double.NEGATIVE_INFINITY 或 Double.POSITIVE_INFINITY。注意,即使在返回值为有限值的情况下,此转换也可能丢失关于 BigDecimal 值精度的信息。

获取标度、精度、正负号

  • int  signum()  返回此 BigDecimal 的正负号函数。当此 BigDecimal 的值为负、零或正时,返回 -1、0 或 1。
  • int  precision()  返回此 BigDecimal 的精度。(精度是非标度值的数字个数。)零值的精度是 1。
  • int  scale()  返回此 BigDecimal 的标度。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。例如, -3 标度是指非标度值乘以 1000。

字符串形式

  • String  toEngineeringString()  返回此 BigDecimal 的字符串表示形式,需要指数时,则使用工程计数法。
  • String  toPlainString()  返回不带指数字段的此 BigDecimal 的字符串表示形式。

转换为BigInteger

  • BigInteger  toBigInteger()  将此 BigDecimal 转换为 BigInteger。
  • BigInteger  toBigIntegerExact()  将此 BigDecimal 转换为 BigInteger,以检查丢失的信息。
  • BigInteger  unscaledValue()  返回其值为此 BigDecimal 的非标度值 的 BigInteger。计算 (this * 10^this.scale())。

重载自Object的方法

  • int  compareTo(BigDecimal val)  将此 BigDecimal 与指定的 BigDecimal 比较。
  • int  hashCode()  返回此 BigDecimal 的哈希码。
  • boolean  equals(Object x)  比较此 BigDecimal 与指定的 Object 的相等性。
  • String  toString()  返回此 BigDecimal 的字符串表示形式,如果需要指数,则使用科学记数法。

2017-8-26

来自为知笔记(Wiz)

时间: 2024-09-30 06:18:14

BigDecimal 小数 浮点数 精度 财务计算的相关文章

java中小数的处理:高精度运算用bigDecimal类,精度保留方法,即舍入方式的指定

一. 计算机的小数计算一定范围内精确,超过范围只能取近似值: 计算机存储的浮点数受存储bit位数影响,只能保证一定范围内精准,超过bit范围的只能取近似值. java中各类型的精度范围参见:http://blog.csdn.net/longshenlmj/article/details/47616481 编程时注意: doulbe类型的数,不能用等号判定是否相等(或者是一定范围内可以).因为两次同样的计算(除法)结果可能出现小数部分不同.甚至极端的时候,初始化两个小数时,都可能不相等(用数值和字

js浮点数精度丢失问题及如何解决js中浮点数计算不精准

js中进行数字计算时候,会出现精度误差的问题.先来看一个实例: console.log(0.1+0.2===0.3);//false console.log(0.1+0.1===0.2);//true 上面第一个的输出会超出我们的常识,正常应该为true,这里为什么会是false呢,直接运行会发现0.1+0.2在js中计算的结果是: console.log(0.1+0.2);//输出0.30000000000000004 这对于浮点数的四则运算(加减乘除),几乎所有的编程语言都会出现上面类似的精

Java 浮点数精度丢失

Java 浮点数精度丢失 问题引入 昨天帮室友写一个模拟发红包抢红包的程序时,对金额统一使用的 double 来建模,结果发现在实际运行时程序的结果在数值上总是有细微的误差,程序运行的截图: 输入依次为:红包个数,抢红包的人数,选择固定金额红包还是随机金额红包,每个红包的金额(此例只有一个红包). 注意到程序最后的结果是有问题的,我们只有一个金额为 10 的红包,一个人去抢,所以正确结果应该为这个人抢到了 10 RMB. 为了使问题更加明显,我们测试一个更加简单的例子: public class

又见浮点数精度问题

今天看到一篇文章:http://younglab.blog.51cto.com/416652/241886,大概是说在使用Javascript进行下面的浮点数计算时出现了问题: obj.style.opacity =  (parseInt(obj.style.opacity *100) + 1)/100; obj.style.opacity是一个浮点数,范围从0~1,初始值为0.这句代码每隔一小段时间执行一次,从而让目标由透明慢慢变为不透明(淡入效果). 问题是,起初obj.style.opac

浮点数在金额计算中的使用总结

浮点数在金额计算中的使用总结(摘自~~) double 和 float 类型的变量不适合用作金额计算是java语言使用中的基本知识,但在实际应用中此基本常识经常被程序员忽视,想当然的用在了实际的金额计算场景中,造成难以察觉的错误.在此对金额计算的使用方法做个总结,以规范后续使用. 1. double和float 的不准确 <effective Java>中指出,float和double类型主要是为科学计算和工程计算而设计的,不应该被用于需要精确结果的场合,尤其不适合于货币计算,见如下代码: p

poj 百练 2765 八进制小数(精度问题)

2765:八进制小数 查看 提交 统计 提示 提问 总时间限制:  1000ms  内存限制:  65536kB 描述 八进制小数可以用十进制小数精确的表示.比如,八进制里面的0.75等于十进制里面的0.963125 (7/8 + 5/64).所有小数点后位数为n的八进制小数都可以表示成小数点后位数不多于3n的十进制小数. 你的任务是写一个程序,把(0, 1)中的八进制小数转化成十进制小数. 输入 输入包括若干八进制小数,每个小数占用一行.每个小数的形式是0.d1d2d3 ... dk,这里di

一个由于浮点数精度导致的错误

今天看到一篇文章:http://younglab.blog.51cto.com/416652/241886,大概是说在使用Javascript进行下面的浮点数计算时出现了问题: obj.style.opacity = (parseInt(obj.style.opacity *100) + 1)/100; obj.style.opacity是一个浮点数,范围从0~1,初始值为0.这句代码每隔一小段时间执行一次,从而让目标由透明慢慢变为不透明(淡入效果).起初,obj.style.opacity能够

php 浮点数对比和计算

Warning 浮点数精度 显然简单的十进制分数如同 0.1 或 0.7 不能在不丢失一点点精度的情况下转换为内部二进制的格式.这就会造成混乱的结果:例如,floor((0.1+0.7)*10)通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 .... 这和一个事实有关,那就是不可能精确的用有限位数表达某些十进制分数.例如,十进制的1/3 变成了 . . .. 所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等. 计算请用bc_math函数

【解码】浮点数精度问题 | 为什么(int)(32.3 x 100) = 3229?

零 | 序 前几天在找一个代码问题时,苦思不得其解,简直要怀疑人生.查看各种参数,输入输出,都符合条件,最后各种排除法之后,定位到一段简单的代码,简化后大致如下: #include<stdio.h> int main() { double a = 32.3; int b = 100; int c = (int)(a*b); printf("c = %d",c); //c = 3229 return 0; } 原代码中本来预想c应该会等于3230,可是最后的结果却是3229!