- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java BigDecimal详解_动力节点Java学院整理由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
1.引言 。
借用《Effactive Java》这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算。他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合。但是,商业计算往往要求结果精确,例如银行存款数额,这时候BigDecimal就派上大用场啦。 。
2.BigDecimal简介 。
BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负scale 次幂。因此,BigDecimal表示的数值是(unscaledValue × 10-scale).
3.测试代码 。
3.1构造函数(主要测试参数类型为double和String的两个常用构造函数) 。
1
2
3
4
|
BigDecimal aDouble =
new
BigDecimal(
1.22
);
System.out.println(
"construct with a double value: "
+ aDouble);
BigDecimal aString =
new
BigDecimal(
"1.22"
);
System.out.println(
"construct with a String value: "
+ aString);
|
你认为输出结果会是什么呢?如果你没有认为第一个会输出1.22,那么恭喜你答对了,输出结果如下: 。
1
2
|
construct with a doublevalue:
1.2199999999999999733546474089962430298328399658203125
construct with a String value:
1.22
|
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构造方法.
3、当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)方法,然后使用BigDecimal(String)构造方法,将double转换为String。要获取该结果,请使用static valueOf(double)方法.
3.2 加法操作 。
1
2
3
4
5
|
BigDecimal a =
new
BigDecimal(
"1.22"
);
System.out.println(
"construct with a String value: "
+ a);
BigDecimal b =
new
BigDecimal(
"2.22"
);
a.add(b);
System.out.println(
"aplus b is : "
+ a);
|
我们很容易会认为会输出:
construct with a Stringvalue: 1.22 。
a plus b is :3.44 。
但实际上a plus b is : 1.22 。
4.源码分析 。
4.1 valueOf(doubleval)方法 。
1
2
3
4
5
6
7
|
public
static
BigDecimal valueOf(
double
val) {
// Reminder: a zero double returns '0.0', so we cannotfastpath
// to use the constant ZERO. This might be important enough to
// justify a factory approach, a cache, or a few private
// constants, later.
returnnew BigDecimal(Double.toString(val));
//见3.1关于JDK描述的第三点
}
|
4.2 add(BigDecimal augend)方法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public
BigDecimal add(BigDecimal augend) {
long
xs =
this
.intCompact;
//整型数字表示的BigDecimal,例a的intCompact值为122
long
ys = augend.intCompact;
//同上
BigInteger fst = (
this
.intCompact !=INFLATED) ?
null
:
this
.intVal;
//初始化BigInteger的值,intVal为BigDecimal的一个BigInteger类型的属性
BigInteger snd =(augend.intCompact !=INFLATED) ?
null
: augend.intVal;
int
rscale =
this
.scale;
//小数位数
long
sdiff = (
long
)rscale - augend.scale;
//小数位数之差
if
(sdiff !=
0
) {
//取小数位数多的为结果的小数位数
if
(sdiff <
0
) {
int
raise =checkScale(-sdiff);
rscale =augend.scale;
if
(xs ==INFLATED ||
(xs = longMultiplyPowerTen(xs,raise)) ==INFLATED)
fst =bigMultiplyPowerTen(raise);
}
else
{
int
raise =augend.checkScale(sdiff);
if
(ys ==INFLATED ||(ys =longMultiplyPowerTen(ys,raise)) ==INFLATED)
snd = augend.bigMultiplyPowerTen(raise);
}
}
if
(xs !=INFLATED && ys !=INFLATED) {
long
sum = xs + ys;
if
( (((sum ^ xs) &(sum ^ ys))) >= 0L)
//判断有无溢出
return
BigDecimal.valueOf(sum,rscale);
//返回使用BigDecimal的静态工厂方法得到的BigDecimal实例
}
if
(fst ==
null
)
fst =BigInteger.valueOf(xs);
//BigInteger的静态工厂方法
if
(snd ==
null
)
snd =BigInteger.valueOf(ys);
BigInteger sum =fst.add(snd);
return
(fst.signum == snd.signum) ?
new
BigDecimal(sum,INFLATED, rscale,
0
) :
new
BigDecimal(sum,compactValFor(sum),rscale,
0
);
//返回通过其他构造方法得到的BigDecimal对象
}
|
以上只是对加法源码的分析,减乘除其实最终都返回的是一个新的BigDecimal对象,因为BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以a.add(b);虽然做了加法操作,但是a并没有保存加操作后的值,正确的用法应该是a=a.add(b); 。
5.总结 。
(1)商业计算使用BigDecimal.
(2)尽量使用参数类型为String的构造函数.
(3) BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值.
(4)我们往往容易忽略JDK底层的一些实现细节,导致出现错误,需要多加注意.
以上所述是小编给大家介绍的Java BigDecimal详解_动力节点Java学院整理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
最后此篇关于Java BigDecimal详解_动力节点Java学院整理的文章就讲到这里了,如果你想了解更多关于Java BigDecimal详解_动力节点Java学院整理的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
大家好,我是汤师爷~ 什么是订单履约系统? 订单履约是从消费者下单支付到收到商品的全流程管理过程,包括订单接收、订单派单、库存分配、仓储管理和物流配送等环节,核心目标是确保商品准时、准确地送达消费
大家好,我是汤师爷~ 今天聊聊促销系统整体规划。 各类促销活动的系统流程,可以抽象为3大阶段: B端促销活动管理:商家运营人员在后台系统中配置和管理促销活动,包括设定活动基本信息、使用规则
全称“Java Virtual Machine statistics monitoring tool”(statistics 统计;monitoring 监控;tool 工具) 用于监控虚拟机的各种运
主要是讲下Mongodb的索引的查看、创建、删除、类型说明,还有就是Explain执行计划的解释说明。 可以转载,但请注明出处。  
1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发。 2>循环服务器和并发服务器
详解 linux中的关机和重启命令 一 shutdown命令 shutdown [选项] 时间 选项: ?
首先,将json串转为一个JObject对象: ? 1
matplotlib官网 matplotlib库默认英文字体 添加黑体(‘SimHei')为绘图字体 代码: plt.rcParams['font.sans-serif']=['SimHei'
在并发编程中,synchronized关键字是常出现的角色。之前我们都称呼synchronized关键字为重量锁,但是在jdk1.6中对synchronized进行了优化,引入了偏向锁、轻量锁。本篇
一般我们的项目中会使用1到2个数据库连接配置,同程艺龙的数据库连接配置被收拢到统一的配置中心,由DBA统一配置和维护,业务方通过某个字符串配置拿到的是Connection对象。  
实例如下: ? 1
1. MemoryCahe NetCore中的缓存和System.Runtime.Caching很相似,但是在功能上做了增强,缓存的key支持object类型;提供了泛型支持;可以读缓存和单个缓存
argument是javascript中函数的一个特殊参数,例如下文,利用argument访问函数参数,判断函数是否执行 复制代码 代码如下: <script
一不小心装了一个Redis服务,开了一个全网的默认端口,一开始以为这台服务器没有公网ip,结果发现之后悔之莫及啊 某天发现cpu load高的出奇,发现一个minerd进程 占了大量cpu,googl
今天写这个是为了 提醒自己 编程过程 不仅要有逻辑 思想 还有要规范 代码 这样可读性 1、PHP 编程规范与编码习惯最主要的有以下几点: 1 文件说明 2 funct
摘要:虚拟机安装时一般都采用最小化安装,默认没有lspci工具。一台测试虚拟网卡性能的虚拟机,需要lspci工具来查看网卡的类型。本文描述了在一个虚拟机中安装lspci工具的具体步骤。 由于要测试
1、修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统
目录 算术运算符 基本四则运算符 增量赋值运算符 自增/自减运算符 关系运算符 逻
如下所示: ? 1
MapperScannerConfigurer之sqlSessionFactory注入方式讲解 首先,Mybatis中的有一段配置非常方便,省去我们去写DaoImpl(Dao层实现类)的时间,这个
我是一名优秀的程序员,十分优秀!