Java Bigdecimal使用原理详解

一般来说,一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法进行精确计算。但是Java的设计者给编程人员提供了一个很有用的类BigDecimal,他可以完善float和double类无法进行精确计算的缺憾。

BigDecimal类位于java.maths类包下。首先我们来看下如何构造一个BigDecimal对象。它的构造函数很多,这里挑选最常用的两个来演示一下:一个就是BigDecimal(double val),另一个就是BigDecimal(String str)。这两个看上去没什么太大区别,但是正像API描述中说:

/*The results of this constructor can be somewhat unpredictable. One might assume that
new BigDecimal(.1) is exactly equal to .1, but it is actually equal
to .1000000000000000055511151231257827021181583404541015625. This is so because .1
cannot be represented exactly as a double (or, for that matter, as a binary fraction
of any finite length). Thus, the long value that is being passed in to the constructor
is not exactly equal to .1, appearances nonwithstanding.
The (String) constructor, on the other hand, is perfectly predictable: new BigDecimal
(".1") is exactly equal to .1, as one would expect. Therefore, it is generally
recommended that the (String) constructor be used in preference to this one.*/

也就是说利用double作为参数的构造函数,无法精确构造一个BigDecimal对象,需要自己指定一个上下文的环境,也就是指定精确位。而利用String对象作为参数传入的构造函数能精确的构造出一个BigDecimal对象。请看下面的代码:

import java.math.*;
public class TestBigDecimal {
 public static void main(String args[]){
  BigDecimal bd = new BigDecimal( "10.123");
  BigDecimal bd1 = new BigDecimal(10.123);
  System.out.println(bd +"/n"+ bd1);
 }
}
运行后输出:

10.123
10.1229999999999993320898283855058252811431884765625

所以我们在选择构造函数时,要看具体需求而定。

另外,很多人会问到怎么将基本类型,如int,float,double,long,和BigDecimal对象相互转换。很简单:

基本类型通过构造函数转换成对应的BigDecimal对象,而BigDecimal类提供了诸如intValue(), floatValue(), doubleValue(), longValue()方法来将BigDecimal对象转换成对应的值。

一、BigDecimal 的加减乘除

BigDecimal bignum1 = new BigDecimal("10");
BigDecimal bignum2 = new BigDecimal("5");
BigDecimal bignum3 = null; 

//加法
bignum3 = bignum1.add(bignum2);
System.out.println("和 是:" + bignum3); 

//减法
bignum3 = bignum1.subtract(bignum2);
System.out.println("差 是:" + bignum3); 

//乘法
bignum3 = bignum1.multiply(bignum2);
System.out.println("积 是:" + bignum3); 

//除法
bignum3 = bignum1.divide(bignum2);
System.out.println("商 是:" + bignum3);

二、BigDecimal 的比较大小。

BigDecimal num1 = new BigDecimal("0");
BigDecimal num2 = new BigDecimal("1");
BigDecimal num3 = new BigDecimal("2");
BigDecimal num = new BigDecimal("1"); //用做比较的值
System.out.println(num1.compareTo(num)); //小于 时,返回 -1
System.out.println(num2.compareTo(num)); //等于 时,返回 0
System.out.println(num3.compareTo(num)); //大于 时,返回 1

补充:

BigInteger 也可以存放比较大的数, 和 BigDecimal 的区别是 :BigInteger 存放的是大的整数,而BigDecimal 存放大的小数

继续补充一下,用BigDecimal 写个for循环。

for (BigDecimal i = new BigDecimal("0"); i.compareTo(new BigDecimal("10")) != 1; i = i.add(new BigDecimal("1"))) {
 System.out.print(i + "\t");
}

控制台打印的是从0 到 10 。

三、Java中的BigDecimal使用注意事项

1.BigDecial是immutable的,就像String一样,它的所有操作都会生成一个新的对象,所以

amount.add( thisAmount );

是错误的;而应该是:

amount = amount.add( thisAmount );

2. 不要用equals方法来比较BigDecimal对象,因为它的equals方法会比较scale,如果scale不一样,它会返回false;

BigDecimal a = new BigDecimal("2.00");
BigDecimal b = new BigDecimal("2.0");
print(a.equals(b)); // false

所以你应该使用compareTo()和signum()方法

a.compareTo(b); // returns (-1 if a < b), (0 if a == b), (1 if a > b)
a.signum(); // returns (-1 if a < 0), (0 if a == 0), (1 if a > 0)

3. 使用BigDecimal的字符串构造函数,不要使用double参数的构造函数,否则的话会出现你不想要的结果。

例如下面的代码分别使用double和String的构造函数,然后使用HALF_EVEN的round方法,但是输出结果不一样

System.out.println("==================");
for(int i = 0; i < 10; i ++) {
 StringBuffer sb = new StringBuffer();
 sb.append("0.");
 sb.append(i);
 sb.append("5");
 BigDecimal bdx = new BigDecimal(sb.toString());
 System.out.println(sb + " " +bdx.setScale(1, RoundingMode.HALF_EVEN));
} 

System.out.println("==================");
for(int i = 0; i < 10; i ++) {
 StringBuffer sb = new StringBuffer();
 sb.append("0.");
 sb.append(i);
 sb.append("5");
 BigDecimal bdx = new BigDecimal(Double.valueOf(sb.toString()));
 System.out.println(sb + " " +bdx.setScale(1, RoundingMode.HALF_EVEN));
}

输出是:

==================
0.05 0.0
0.15 0.2
0.25 0.2
0.35 0.4
0.45 0.4
0.55 0.6
0.65 0.6
0.75 0.8
0.85 0.8
0.95 1.0
==================
0.05 0.1
0.15 0.1
0.25 0.2
0.35 0.3
0.45 0.5
0.55 0.6
0.65 0.7
0.75 0.8
0.85 0.8
0.95 0.9

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java中BigDecimal精度和相等比较的坑

    为什么要有BigDecimal ,他是干什么的 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合.但是,商业计算往往要求结果精确,这时候就要使用BigDecimal啦. 什么是BigDecimal BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成.如果为零或正数,则标度是小数点后的

  • Java Math类、Random类、System类及BigDecimal类用法示例

    本文实例讲述了Java Math类.Random类.System类及BigDecimal类用法.分享给大家供大家参考,具体如下: Math类 Math的方法 package cn.itcast_01; /* * Math:用于数学运算的类. * 成员变量: * public static final double PI * public static final double E * 成员方法: * public static int abs(int a):绝对值 * public static

  • Java BigInteger类,BigDecimal类,Date类,DateFormat类及Calendar类用法示例

    本文实例讲述了Java BigInteger类,BigDecimal类,Date类,DateFormat类及Calendar类用法.分享给大家供大家参考,具体如下: BigInteger类 发 package cn.itcast_01; import java.math.BigInteger; /* * BigInteger:可以让超过Integer范围内的数据进行运算 * * 构造方法: * BigInteger(String val) */ public class BigIntegerDe

  • Java BigDecimal和double示例及相关问题解析

    BigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作.BigDecimal类的常用方法如表1所示. 表1 BigDecimal类的常用方法 序号 方    法 类型 描    述 1 public BigDecimal(double val) 构造 将double表示形式转换 为BigDecimal 2 public BigDecimal(in

  • Java使用BigDecimal进行运算封装的实际案例

    日常对于金额计算,应该都是用的BigDecimal,可是苦于没有好的工具类方法,现在贡献一个我正在用的对于数字计算的工具类,项目中就是用的这个,简单粗暴好用,话不多说,代码奉上(该工具类需要引入google的一个jar,com.google.common.base.Optional,具体maven引入看文章末尾): import java.math.BigDecimal; public class NumberArithmeticUtils { /** * BigDecimal的加法运算封装 *

  • Java中BigDecimal的加减乘除、比较大小与使用注意事项

    前言 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合.但是,商业计算往往要求结果精确,在java 里面,int 的最大值是:2147483647,现在如果想用比这个数大怎么办?换句话说,就是数值较大,这时候就用到了BigDecimal ,关于BigDecimal 的介绍

  • Java中BigDecimal类与int、Integer使用总结

    前言 我们都知道浮点型变量在进行计算的时候会出现丢失精度的问题.如下一段代码: System.out.println(0.05 + 0.01); System.out.println(1.0 - 0.42); System.out.println(4.015 * 100); System.out.println(123.3 / 100); 输出: 0.060000000000000005 0.5800000000000001 401.49999999999994 1.23299999999999

  • 详谈Java中BigDecimal的一个除法异常

    如下所示: java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. 说明遇到除不尽的情况了,需要指定商的小数精度和舍入模式. 比如: a=b.divide(c,2,RoundingMode.HALF_UP); 以上这篇详谈Java中BigDecimal的一个除法异常就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Java Bigdecimal使用原理详解

    一般来说,一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法进行精确计算.但是Java的设计者给编程人员提供了一个很有用的类BigDecimal,他可以完善float和double类无法进行精确计算的缺憾. BigDecimal类位于java.maths类包下.首先我们来看下如何构造一个BigDecimal对象.它的构造函数很多,这里挑选最常用的两个来演示一下:一个就是BigDecimal(double val),另一个就是BigDecimal(String s

  • Java binarysearch方法原理详解

    这篇文章主要介绍了Java binarysearch方法原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 首先 数组排序需要import java.util.Arrays类 binarysearch有两个用法,一个是在整个数组里搜索,一个是在指定范围搜索,其实都是差不多的,可以将前者视为后者的特殊情况. 用法1 binarySearch(Object[], Object key) Object是目标数组,key是目标值,要求目标数组必须要

  • Java BigDecimal类用法详解

    一.简介 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数.在实际应用中,需要对更大或者更小的数进行运算和处理.float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal.BigDecimal所创建的是对象,我们不能使用传统的+.-.*./等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法.方法中的参数也必须是BigDe

  • Java BigDecimal基础用法详解

    目录 一.BigDecimal概述 二.BigDecimal常用构造函数 2.1.常用构造函数 2.2.使用问题分析 三.BigDecimal常用方法详解 3.1.常用方法 3.2.BigDecimal大小比较 四.BigDecimal格式化 五.BigDecimal常见异常 5.1.除法的时候出现异常 六.BigDecimal总结 6.1.总结 6.2.工具类推荐 一.BigDecimal概述 一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Do

  • java BigDecimal类案例详解

    目录 前言 一.介绍 二.知识点介绍 三.知识点详解 1.概述 2.BigDecimal构造方法 3.源码的描述 4.BigDecimal加减乘除运算 5.总结 6.精炼练习 6.1  题目 6.2 实验步骤 结语 前言 只要认真计划一件事,并且一边坚持一边调整,往往会完成得十分出色.懈怠的情绪谁都会有,不要担心自己比别人走得慢,也不要因暂时的挫折心灰意冷,只要不断调整心态,不停下脚步,最终能抵达终点. 一.介绍 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制

  • Java BigDecimal正确用法详解

    目录 一.背景 二.事故案例 1.问题 2.问题复现 3.源码分析 4.原因分析 三.总结 四.工具类 一.背景 BigDecimal 平时主要用于计算金钱时,其自身提供了很多的构造方法,但是这些构造方法使用不当会造成精度丢失,从而引起事故. 二.事故案例 1.问题 收银台计算商品价格报错,导致订单无法支付 2.问题复现 public static void main(String[] args) { BigDecimal bigDecimal=new BigDecimal(88); Syste

  • Java BigDecimal类用法详解

    1.引言 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合.但是,商业计算往往要求结果精确,这时候BigDecimal就派上大用场啦. 2.BigDecimal简介 BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成.如果为零或正数

  • java线程优先级原理详解

    java 中的线程优先级的范围是1-10,默认的优先级是5.10最高. MIN_PRIORITY 1 MAX_PRIORITY 10 NORM_PRIORITY 5 优先级高的获得cpu的几率更大些,不是优先级高的就先执行完,线程优先级随机特性 在java中,线程的优先级具有继承性,例如A线程启动B线程,则A和B的优先级是一样的 线程创建后,可通过调用setPriority()方法改变优先级. public class Test5 { public static class TheadT ext

  • Java中BigDecimal的基本运算(详解)

    BigDecimal一共有4个够造方法,让来看看其中比较常用的两种用法: 第一种:BigDecimal(double val) Translates a double into a BigDecimal. 第二种:BigDecimal(String val) Translates the String repre sentation of a BigDecimal into a BigDecimal. 使用BigDecimal要用String来够造,要做一个加法运算,需要先将两个浮点数转为Str

  • java并发等待条件的实现原理详解

    前言 前面介绍了排它锁,共享锁的实现机制,本篇继续学习AQS中的另外一个内容-Condition.想必学过java的都知道Object.wait和Object.notify,同时也应该知晓这两个方法的使用离不开synchronized关键字.synchronized是jvm级别提供的同步原语,它的实现机制隐藏在jvm实现中.作为Lock系列功能中的Condition,就是用来实现类似 Object.wait和Object.notify 对应功能的. 使用场景 为了更好的理解Lock和Condit

随机推荐