服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java BigDecimal案例详解

Java BigDecimal案例详解

2021-11-13 11:27YangJavaer Java教程

这篇文章主要介绍了Java BigDecimal案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

引言

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

先看下面代码

?
1
2
3
4
5
6
7
public static void main(string[] args)
    {
        system.out.println(0.2 + 0.1);
        system.out.println(0.3 - 0.1);
        system.out.println(0.2 * 0.1);
        system.out.println(0.3 / 0.1);
    }

运行结果如下

Java BigDecimal案例详解

   你认为你看错了,但结果却是是这样的。问题在哪里呢?原因在于我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。我们的cpu表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。

          其实java的float只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.bigdecimal类来进行精确计算。

bigdecimal构造方法

  1. public bigdecimal(double val)    将double表示形式转换为bigdecimal *不建议使用
  2. public bigdecimal(int val)  将int表示形式转换成bigdecimal
  3. public bigdecimal(string val)  将string表示形式转换成bigdecimal

为什么不建议采用第一种构造方法呢?来看例子

?
1
2
3
4
5
6
7
8
9
public static void main(string[] args)
    {
        bigdecimal bigdecimal = new bigdecimal(2);
        bigdecimal bdouble = new bigdecimal(2.3);
        bigdecimal bstring = new bigdecimal("2.3");
        system.out.println("bigdecimal=" + bigdecimal);
        system.out.println("bdouble=" + bdouble);
        system.out.println("bstring=" + bstring);
    }

运行结果如下

Java BigDecimal案例详解

为什么会出现这种情况呢?

 jdk的描述: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构造方法。

double必须用作bigdecimal的源时,请使用double.tostring(double)转成string,然后使用string构造方法,或使用bigdecimal的静态方法valueof,如下

?
1
2
3
4
5
6
7
8
9
public static void main(string[] args)
    {
        bigdecimal bdouble1 = bigdecimal.valueof(2.3);
        bigdecimal bdouble2 = new bigdecimal(double.tostring(2.3));
 
        system.out.println("bdouble1=" + bdouble1);
        system.out.println("bdouble2=" + bdouble2);
        
    }

结果如下

Java BigDecimal案例详解

bigdecimal加减乘除运算

对于常用的加,减,乘,除,bigdecimal类提供了相应的成员方法。

?
1
2
3
4
5
6
7
public bigdecimal add(bigdecimal value);                        //加法
 
public bigdecimal subtract(bigdecimal value);                   //减法
 
public bigdecimal multiply(bigdecimal value);                   //乘法
 
public bigdecimal divide(bigdecimal value);                     //除法

大概的用法如下

?
1
2
3
4
5
6
7
8
9
10
public static void main(string[] args)
    {
        bigdecimal a = new bigdecimal("4.5");
        bigdecimal b = new bigdecimal("1.5");
 
        system.out.println("a + b =" + a.add(b));
        system.out.println("a - b =" + a.subtract(b));
        system.out.println("a * b =" + a.multiply(b));
        system.out.println("a / b =" + a.divide(b));
    }

运行结果

Java BigDecimal案例详解

这里有一点需要注意的是除法运算divide.

 bigdecimal除法可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.arithmeticexception: non-terminating decimal expansion; no exact representable decimal result.

其实divide方法有可以传三个参数

public bigdecimal divide(bigdecimal divisor, int scale, int roundingmode)
第一参数表示除数, 第二个参数表示小数点后保留位数
第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
round_ceiling    //向正无穷方向舍入
 
round_down    //向零方向舍入
 
round_floor    //向负无穷方向舍入
 
round_half_down    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
 
round_half_even    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用round_half_up,如果是偶数,使用round_half_down
 
round_half_up    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
 
round_unnecessary    //计算结果是精确的,不需要舍入模式
 
round_up    //向远离0的方向舍入

按照各自的需要,可传入合适的第三个参数。四舍五入采用 round_half_up

需要对bigdecimal进行截断和四舍五入可用setscale方法,例:

?
1
2
3
4
5
6
7
public static void main(string[] args)
    {
        bigdecimal a = new bigdecimal("4.5635");
 
        a = a.setscale(3, roundingmode.half_up);    //保留3位小数,且四舍五入
        system.out.println(a);
    }

减乘除其实最终都返回的是一个新的bigdecimal对象,因为biginteger与bigdecimal都是不可变的(immutable)的
,在进行每一步运算时,都会产生一个新的对象 

?
1
2
3
4
5
6
7
8
9
10
public static void main(string[] args)
    {
        bigdecimal a = new bigdecimal("4.5");
        bigdecimal b = new bigdecimal("1.5");
        a.add(b);
 
        system.out.println(a);  //输出4.5. 加减乘除方法会返回一个新的bigdecimal对象,原来的a不变
 
 
    }

总结

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

到此这篇关于java bigdecimal案例详解的文章就介绍到这了,更多相关java bigdecimal内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/YangJavaer/p/6056394.html

延伸 · 阅读

精彩推荐
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7482021-02-04
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17