BigInteger 和BigDecimal
出处:为什么会想到大数呢?是因为最近在写leetcode刷题的时候钻牛角尖非要实现数组加1的问题导致的。(leetcode 66 加1问题)不过ps自己对大数还是用的少了,导致害怕用,然后leetcode用了还报错。(这个自己感觉代码没问题估计不让用吧)
BigInteger (大整数)
这个类主要就是为了长度过长超过long整数基本类型而生产出来的,它的内部源码可以简单看一下变量就一目了然。
final int signum; // 符号标志, -1 : 负数, 0 : 零, 1 : 正数
final int[] mag; // 存放大整数二进制位的数组, 大端存储
/*
** 下面的变量都是为了懒求值而设置的, 暂时不用管.
* 所谓懒求值是指当用到的时候才求值;
*
** 而求过之后由于BigInteger是不可变的,
* 这些所求也不会变, 所以就利用变量存下,
* 当第二次求这些的时候, 直接返回即可;
*
** 之所以存放这些值+1或+2(plusOne plusTwo),
* 是为了方便判断是否被求过.
*/
private int bitCountPlusOne;
private int bitLengthPlusOne;
private int lowestSetBitPlusTwo;
private int firstNonzeroIntNumPlusTwo;
通过源码的查看了解到它的底层使用了int数组来实现,而int数组来讲可以实现几乎无限长,而一个int类型是有32位,可想而知很大,注意到它跟String一样很特殊里面使用final修饰说明不可修改,只能利用里面分装好的方法进行操作也有着一定局限性,那么用到的时候也很简单跟着以下方法目录进行调用就可以啦。
这边就做个方法链接:https://www.w3schools.cn/javamath/java_math_biginteger.asp
BigDecimal(大浮点数)
首先介绍为什么浮点数 float 或 double 运算的时候会有精度丢失的风险?
一句话概括就是因为计算机二进制表示时会宽度不够小数被截断导致了精度的丢失。
通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal 来做的。
源码中几个重要属性
// 若BigDecimal的绝对值小于Long.MAX_VALUE,放在这个变量中
//public static final long MIN_VALUE = 0x8000000000000000L;
private final transient long intCompact;
//BigDecimal的标度(小数点),
//输入数除以10的scale次幂(32 位的整数标度)
private final int scale;
// BigDecimal的未scale的值,BigInteger是
// 一个任意长度的整数(整数非标度值)
private final BigInteger intVal;
// BigDecimal的精度(精度是非标度值的数字个数)
private transient int precision;
//toString后缓存
private transient String stringCache;
可以很熟悉看到它基于BigInteger 实现。
这边注意详细想看一下源码解析的地址哦!说不定有惊喜想法呢?https://zhuanlan.zhihu.com/p/339905119我从这里面了解到这么重要一个小点。
BigDecimal坑
- double 参数的构造方法,不允许使用!!!因为它不能精确的得到相应的值;
- String 构造方法是完全可预知的: 写入 new BigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的0.1; 因此,通常建议优先使用 String 构造方法;
- 静态方法 valueOf(double val) 内部实现,仍是将 double 类型转为 String 类型; 这通常是将 double(或float)转化为 BigDecimal 的首选方法;
做个方法链接:https://www.w3schools.cn/javamath/java_math_bigdecimal.html