第三篇

先介绍以BigInteger为构造参数的构造器

     public BigDecimal(BigInteger val) {// 根据BigInteger创建BigDecimal对象
scale = 0;// BigInteger为整数因此有效小数位数为0
intVal = val;
intCompact = compactValFor(val);
} public BigDecimal(BigInteger unscaledVal, int scale) {// 这个与上一个差不多但是指定了有效小数位数,但是最终的BigDecimal的数值为unscaledVal*10^-scale次方
// Negative scales are now allowed
this.intVal = unscaledVal;
this.intCompact = compactValFor(unscaledVal);
this.scale = scale;
} public BigDecimal(BigInteger val, MathContext mc) {// 该方法转发调用下面的构造器
this(val,0,mc);
} public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
long compactVal = compactValFor(unscaledVal);
int mcp = mc.precision;
int prec = 0;
if (mcp > 0) { // do rounding,根据MathContext中的有效位数进行舍去操作,具体解析见第一篇BigDecimal源码解析文章
int mode = mc.roundingMode.oldMode;
if (compactVal == INFLATED) {
prec = bigDigitLength(unscaledVal);
int drop = prec - mcp;
while (drop > 0) {
scale = checkScaleNonZero((long) scale - drop);
unscaledVal = divideAndRoundByTenPow(unscaledVal, drop, mode);
compactVal = compactValFor(unscaledVal);
if (compactVal != INFLATED) {
break;
}
prec = bigDigitLength(unscaledVal);
drop = prec - mcp;
}
}
if (compactVal != INFLATED) {
prec = longDigitLength(compactVal);
int drop = prec - mcp; // drop can't be more than 18
while (drop > 0) {
scale = checkScaleNonZero((long) scale - drop);
compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mode);
prec = longDigitLength(compactVal);
drop = prec - mcp;
}
unscaledVal = null;
}
}
this.intVal = unscaledVal;
this.intCompact = compactVal;
this.scale = scale;
this.precision = prec;// 若MathContext中的有效位数小于等于0,则BigDecimal中的有效位数置为0
}

接下来介绍以int类型为构造参数的构造器

     public BigDecimal(int val) {// 以int数值来创建BigDecimal对象,int类型为整数则有效小数位数为0
this.intCompact = val;
this.scale = 0;
this.intVal = null;// 此时BigDecimal的数值在int类型的表数范围因此也在long类型的表数范围,所以intVal为null
} public BigDecimal(int val, MathContext mc) {// 该构造器在以int类型为参数的同时传入一个MathContext来限制有效位数
int mcp = mc.precision;
long compactVal = val;
int scale = 0;
int prec = 0;
if (mcp > 0) { // do rounding,根据val的位数与MathContext的有效位数修正最终值的有效位数,即进行舍去操作,具体分析见第一篇BigDecimal源码分析文章
prec = longDigitLength(compactVal);
int drop = prec - mcp; // drop can't be more than 18
while (drop > 0) {
scale = checkScaleNonZero((long) scale - drop);
compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
prec = longDigitLength(compactVal);
drop = prec - mcp;
}
}
this.intVal = null;
this.intCompact = compactVal;// BigDecimal对象表示数值的简洁值就是int类型参数val
this.scale = scale;
this.precision = prec;
}

long类型参数的构造器分析

     public BigDecimal(long val) {// 以long类型数值来创建BigDecimal对象,long类型为整数则有效小数位数为0
this.intCompact = val;
this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;// 若val的数值为long类型最小值需要特殊处理,因为此时的val有特殊含义(数值在long类型下溢出)
this.scale = 0;
} public BigDecimal(long val, MathContext mc) {// 该构造器在以long类型为参数的同时传入一个MathContext来限制有效位数
int mcp = mc.precision;
int mode = mc.roundingMode.oldMode;
int prec = 0;
int scale = 0;
BigInteger intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
if (mcp > 0) { // do rounding,根据val的位数与MathContext的有效位数修正最终值的有效位数,即进行舍去操作,具体分析见第一篇BigDecimal源码分析文章
if (val == INFLATED) {// 若val为INFLATED即-2^63,该数位数为19,因此初始化有效位数为19
prec = 19;
int drop = prec - mcp;
while (drop > 0) {
scale = checkScaleNonZero((long) scale - drop);
intVal = divideAndRoundByTenPow(intVal, drop, mode);
val = compactValFor(intVal);
if (val != INFLATED) {
break;
}
prec = bigDigitLength(intVal);
drop = prec - mcp;
}
}
if (val != INFLATED) {
prec = longDigitLength(val);
int drop = prec - mcp;
while (drop > 0) {
scale = checkScaleNonZero((long) scale - drop);
val = divideAndRound(val, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
prec = longDigitLength(val);
drop = prec - mcp;
}
intVal = null;
}
}
this.intVal = intVal;
this.intCompact = val;
this.scale = scale;
this.precision = prec;
}

BigDecimal的原码接下来是一堆的静态方法用于创建BigDecimal对象,几乎没有什么需要分析的,很简单大家可以自己看一看

JDK8 BigDecimal API-创建BigDecimal源码浅析三的更多相关文章

  1. ArrayList类源码浅析(三)

    1.看一个示例 运行上述代码,抛出一个异常: 这是一个典型的并发修改异常,如果把上述代码中的125行注释,把126行打开,运行就能通过了: 原因: 1)因为在迭代的时候,使用的是Itr类的对象,在调用 ...

  2. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  3. Android开发之Theme、Style探索及源码浅析

    1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...

  4. CountDownLatch源码浅析

    Cmd Markdown链接 CountDownLatch源码浅析 参考好文: JDK1.8源码分析之CountDownLatch(五) Java并发之CountDownLatch源码分析 Count ...

  5. Bytom侧链Vapor源码浅析-节点出块过程

    Bytom侧链Vapor源码浅析-节点出块过程 在这篇文章中,作者将从Vapor节点的创建开始,进而拓展讲解Vapor节点出块过程中所涉及的源码. 做为Vapor源码解析系列的第一篇,本文首先对Vap ...

  6. Phoenix创建索引源码过程

    date: 2020-09-27 13:50:00 updated: 2020-09-28 16:30:00 Phoenix创建索引源码过程 org.apache.phoenix.index.Inde ...

  7. redux 源码浅析

    redux 源码浅析 redux 版本号: "redux": "4.0.5" redux 作为一个十分常用的状态容器库, 大家都应该见识过, 他很小巧, 只有 ...

  8. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  9. Struts2源码浅析-ConfigurationProvider

    ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...

随机推荐

  1. Windows10 永久激活查询/激活时间查询/激活查询命令/激活码查询

    1.使用 Windows + R组合快捷键打开运行命令框 运行: slmgr.vbs -dlv       命令 可以查询到Win10的激活信息,包括:激活ID.安装ID.激活截止日期等信息.看不懂的 ...

  2. vue中mint-ui的filed的与blur事件结合实现检查用户输入是否正确

    标题mint-ui的filed与blur事件验证用户输入格式是否正确说明:本人前端菜鸟,只是想借个地方做个笔记,为了以后查阅时比较方便.如有大神有什么建议的地方,欢迎提出来. 1.不得不说,mint- ...

  3. 使php支持pdo_mysql

    1.下载pdo_mysql包 wget https://pecl.php.net/get/PDO_MYSQL-1.0.2.tgz 2.追加编译php,使其module目录下生产pdo_mysql.so ...

  4. VS2008,System.Runtime.InteropServices.COMException (0x800401F3): Invalid class string (Exception from HRESULT: 0x800401F3 (CO_E_CLASSSTRING))

    在VS2008环境中编译调试运行不报错,但在发布的exe文件运行就报错 System.Runtime.InteropServices.COMException (0x800401F3): Invali ...

  5. 201771010118《面向对象程序设计(java)》第四周学习总结

    1.实验目的与要求 (1) 理解用户自定义类的定义: (2) 掌握对象的声明: (3) 学会使用构造函数初始化对象: (4) 使用类属性与方法的使用掌握使用: (5) 掌握package和import ...

  6. (68)Wangdao.com第十一天_JavaScript 数组的常用方法

    数组的常用方法: 向数组末尾添加一个或多个元素,返回新长度 var arr = new Array(); arr.push("唐僧"); // 返回 1 删除数组最后一个元素,返回 ...

  7. Ubuntu 安装 Redis和phpredis扩展

    服务器Ubuntu16.04 环境php7.0+Apache /****************************开始安装Redis****************************/ 1 ...

  8. verilog中signed的使用

    1.在verilog中有时会用signed修饰符来修饰定义的数据,运算的时候也会用$signed()任务来强制转换数据,那么signed的修饰是为什么呢,是为了区分有符号数和无符号数的加法和乘法吗?其 ...

  9. js高级4

    1.Date  类 getDate()返回一个月中的某一天 1-31 getDay() 返回一周中的某一天0-6 getFullyear()返回四位数的年份 getMonth()返回月份 比实际情况小 ...

  10. Lucene.net 的性能探究--Lucene.net 的并发处理能力到底有多强?

    这篇博客并不是证明Lucene.net的性能有多强悍,实际上Lucene.net的并发能力并不让人很满意,这得看你怎么用它. 因为Lucene 本身就是一个搜索引擎的基础框架,相当于一辆车子的发动机, ...