浮点数精确计算——BigDecimal

1、为什么 double(或 float) 不精确?

  • 计算机只认识二进制
  • 十进制小数转换成二进制,一般采用“乘二取整,顺序排列”的方法,但有的小数并不能转换成二进制,如 0.1 就不能直接用二进制表示。它的二进制是0.000110011001100……,这是一个无限循环小数;
  • 为了解决不能转换成二进制的问题,人们想出了一种采用一定的精度,使用近似值表示一个小数的方法:IEEE 754(IEEE 二进制浮点数算数标准)规范的主要思想(IEEE 754 规定了多种表示浮点数值的方式,其中最常用的就是 32 位单精度浮点数 和 64 位双精度浮点数);
  • 所谓精度不同,可以简单理解为保留有效位数不同。

2、BigDecimal 如何精确计数?

  • 看源码就能发现:一个 BigDecimal 实际上是通过一个“无标度值”和一个“标度”来表示一个数的;
【scale】123.45:2
【unscaledValue】123.45:12345
【scale】-3000:0
【unscaledValue】-3000:-3000
* 标度通过 scale 字段来表示
* 无标度值的表示比较复杂
    * 当 unscaled value 超过阈值(默认为 Long.MAX_VALUE)时采用 intVal 字段存储 unscaled value,intCompact 字段存储 Long.MIN_VALUE;
    * 否则对 unscaled value 进行压缩存储到 long 型的 intCompact 字段用于后续计算,intVal 为空。
    * 涉及到的字段如下:
public class BigDecimal extends Number implements Comparable<BigDecimal> {
   
      
    private final BigInteger intVal;
    // 表示标度
    private final int scale; 

    private final transient long intCompact;
}
  • 标度到底是什么?
    • 除了 scale 字段,还提供了 scale() 方法,用来返回这个 BigDecimal 的标度。
    • 如果scale为零或正值,则该值表示这个数字小数点右侧的位数;
    • 如果scale为负数,则该数字的真实值需要乘以10的 该负数的绝对值 的幂。例如,scale为-3,则这个数需要乘1000,即在末尾有3个0。
    • eg:二进制无法表示的 0.1,使用 BigDeci
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值