zoukankan      html  css  js  c++  java
  • Java基础扫盲系列(二)—— Java中BigDecimal和浮点类型

    一直以来我几乎未使用过BigDecimal类型,只有在DB中涉及到金额字段时听说要用Decimal类型,但是今天再项目代码中看到使用BigDecimal表示贷款金额。

    本篇文章不是介绍BigDecimal原理,只是说明BigDecimal和浮点的区别以及其应用场景。

    借用《Effactive Java》这本书中的话:

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

    下面来看几个例子:

     double d1 = 11540;
    double d2 = 0.35;
    System.out.println(d1 * d2);
    

    执行结果:

    4038.9999999999995
    

    但是实际结果应该是:

    4039.00
    

    这类就出现上述Effective Java中提到的double用于科学计算,提供的是精确的快速近似计算,导致失去了精准结果。

     // 科学计数法
    double d3 = 0.0000000000000000111;
    System.out.println(d3);
    

    输出结果:

    1.11E-17
    

    这也是上述提到的double用于科学计算领域,使用了科学计数法。

    但是在实际项目中,特别对于金融领域,对金额十分敏感和精确的前提下不可能使用double或者float的浮点类型:

    • 用于科学计算领域使用了科学计数法
    • 用于大型数值近似计算,结果近似准确

    基于以上,需要新的类型实现精准计算,Java提供BigDecimal类型:

    Immutable, arbitrary-precision signed decimal numbers. A

    • {@code BigDecimal} consists of an arbitrary precision integer
    • unscaled value and a 32-bit integer scale

    由Java docs中可以看出,BigDecimal是不可变的任意进度的十进制数。

    BigDecimal位于java.math包下,正如其包名和类名,该类也提供了很多算术运算:加减乘除。

    这里就不做详细介绍,具体可以查阅api文档。下面可一些例子:

    BigDecimal bigDecimal1 = new BigDecimal("11540");
    BigDecimal bigDecimal2 = new BigDecimal("0.35");
    System.out.println(bigDecimal1.multiply(bigDecimal2));
    

    输出结果:

    4039.00
    

    这里就是精准计算,所以项目应用中金额一般都用BigDecimal类型。

    下面再介绍一些关于BigDecimal中使用到的一些坑和使用原则:

    BigDecimal bigDecimal1 = new BigDecimal(20.11345);
    BigDecimal bigDecimal2 = new BigDecimal("20.11345");
    
    System.out.println(bigDecimal1);
    System.out.println(bigDecimal2);
    

    输出结果:

    20.11345000000000027284841053187847137451171875
    20.11345
    

    在使用BigDecimal的double参数构造函数时,一定要注意看业务场景:是需要double近似还是精确。如果需要精确的场景,在使用前一定要将double转换成String,然后再转换成BigDecimal。否则将都是近似表示。

  • 相关阅读:
    【mybatis】mybatis查询 结果 用map接收,无实体接收 + 关联子表 一并返回主子表的结果
    【mysql】 mybatis实现 主从表 left join 1:n 一对多 分页查询 主表从表都有查询条件 【mybatis】count 统计+JSON查询
    【mysql】获取某个表所有列名【mybatis】
    【mybatis】mybatis中insert操作,返回自增id
    【mybatis】从一个错误,看mybatis中的#和$的区别
    【java】单实例下的 流水号【21位】
    【mysql】新增列 时间戳
    【vue】搭建vue环境以及要安装的所有东西
    【小程序】小程序开发自定义组件的步骤>>>>>>>>>小程序开发过程中报错:jsEnginScriptError
    jmap错误:unknown CollectedHeap type : class sun.jvm.hotspot.gc_interface.CollectedHeap
  • 原文地址:https://www.cnblogs.com/lxyit/p/9366927.html
Copyright © 2011-2022 走看看