java bigdecimal 初始化_Java BigDecimal详解

1.引言

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

2.BigDecimal简介

BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负scale 次幂。因此,BigDecimal表示的数值是(unscaledValue × 10-scale)。

3.测试代码

3.1构造函数(主要测试参数类型为double和String的两个常用构造函数)

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,那么恭喜你答对了,输出结果如下:

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。因此,比较而言,

3、当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)方法,然后使用BigDecimal(String)构造方法,将double转换为String。要获取该结果,请使用staticvalueOf(double)方法。

3.2 加法操作

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)方法

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)方法

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底层的一些实现细节,导致出现错误,需要多加注意。

第 4 课 树莓派5的换源与中文输入法 树莓派换源、中文输入法的安装 阅读详情

相关推荐

BigDecimal类型的数据范围判断与加减乘除操作

使用 compareTo() 方法进行比较时,如果 number 大于等于 lowerBound 并且小于等于 upperBound,则表示 number 在范围内,输出 “Number is between -5 and 5”;在上面的示例中,我们创建了一个BigDecimal对象 number,并指定了初始值为 “-3.5”。然后,我们创建了两个BigDecimal对象 lowerBound 和 upperBound,分别表示下限和上限,其值分别为 “-5” 和 “5”。

舒一笑的博客 2532

Java浮点数精度问题与BigDecimal详解

BigDecimal的主要优势在于它能提供高精度的数值计算,这对于金融、科学等领域至关重要。正确的使用方法:了解如何创建和使用BigDecimal是基础,特别是在创建对象时选择正确的方法(比如使用字符串构造器)。精度和性能的平衡:虽然BigDecimal提供了高精度,但也可能影响性能。因此,在实际应用中需要在精度和性能之间找到平衡。实际应用场景:在金融计算、商业账单处理等多种场景中,BigDecimal都能提供精确可靠的计算结果。

宋小黑的博客 1445

使用BigDecimal计算复利的Java实践项目

复利计算是一种基于利息再次产生利息的计算方法。其核心思想在于利息不仅仅是基于最初的本金计算,而且每一期的利息都会在下一期中产生额外的利息。复利计算通常用于金融投资和贷款计算等场景。复利的计算公式如下:其中:- ( A ) 是未来价值,即本金加上利息的总金额。- ( P ) 是本金(Principal),也就是最初投资或贷款的金额。- ( r ) 是年利率(Rate),表示每一年赚取的利息比例。- ( n ) 是每年计息次数(Number of periods per year)。

weixin_31961675的博客 1135

JavaBigDecimal初始化、加减乘除、大小比较

BigDecimal初始化、加减乘除、大小比较

Cc阿正的博客 6869

decimal在java怎么用?

自己在计算费用时候,因为用了Double类型造成结果与期望值有偏差,所以改用decimal类型进行计算 一,decimal在java中的用BigDecimal表示 @Column(length=10 ,scale=2) // length表示长度 , scale表示小数点后位数 private BigDecimal money; 二,BigDecima...

weixin_45004318的博客 3万+

BigDecimal的使用(初始化,赋值,比大小)

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

weixin_43795761的博客 1万+

Java默认bigdecimal初始值_BigDecimal初始化不要用double类型

在进行单价、总价相关的计算时,就会用到BigDecimal。在初始化时,一个不小心,就可能给自己挖坑。示例如下:public class BigDecimalInitTest {public static void main(String[] args) {BigDecimal amount1=new BigDecimal("0.06");BigDecimal amount2=new BigDec...

weixin_36233098的博客 1万+

java bigdecimal 初始化_java中的BigDecimal详解及使用

1 BigDecimal简介BigDecimal是由任意精度的整数非标度值和32位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负scale 次幂。因此,BigDecimal表示的数值是(unscaledValue × 10-scale)双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行...

weixin_29986051的博客 2315

java bigdecimal 初始化_Java关于BigDecimal的介绍及用法(一)

一、BigDecimal概述​  Javajava.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Fl...

weixin_33384949的博客 1655

java list 初始化赋值_Java面试题之BigDecimal 初始化赋值方式

BigDecimal类对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作。上述代码输出结果:0.10000000000000000555111512312578270211815834045410156250.1分析过程BigDecimal a = new BigDe...

weixin_32135505的博客 1535

string转成bigdecimal_Java面试题之BigDecimal 初始化赋值方式

BigDecimal类对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作。上述代码输出结果:0.10000000000000000555111512312578270211815834045410156250.1分析过程BigDecimal a = new BigDe...

weixin_39655160的博客 2243

java bigdecimal语法_JAVABigDecimal详解

java 四舍五入new BigDecimal(double)及BigDecimal valueOf(double)的区别最近在研究java的四舍五入,其中有一个方法如下new BigDecimal(val).setScale(newScale, BigDecimal.ROUND_HALF_DOWN));其中val是要处理的浮点数newScale表示要保留小数点后几位BigDecimal.ROUN...

weixin_35880116的博客 372

java bigdecimal 初始化_java - 带有BigDecimal javajava.lang.NumberFormatException - 堆栈内存溢出...

我不是一个非常有经验的程序员,所以请原谅这个问题:D我实现了这段短代码来计算第(n)个斐波那契数,但是当我变大时,我的BigDecimal似乎不再起作用。 我得到以下错误:Exception in thread "main" java.lang.NumberFormatExceptionat java.math.BigDecimal.(BigDecimal.java:494)at java.ma...

weixin_39629075的博客 767

java初始化bigdecimal_java – 在BigDecimal上下文中,是否可以使用小整数值初始化的double精确使用?...

有充分证据表明,使用double会导致不准确,只要混合中没有双打,BigDecimal就能保证准确性.但是,如果双重问题是一个小的整数,是否保证了准确性?例如,虽然以下内容不准确/不安全:BigDecimal bdDouble = new BigDecimal(0.1d); // 0.1000000000000000055511151231257827021181583404541015625以下...

weixin_39575502的博客 90

BigDecimal全面剖析

1.加减乘除 add 加 subtract 减 multiply 乘 divide 除 2. 数组 创建数组 BigDecimal[] bigDecimals = new BigDecimal[]{BigDecimal.ZERO,BigDecimal.ZERO}; 如果默认这么创建: BigDecimal[] bigDecimals = new BigDecimal[]; 那么其实他的数组都是null,就像下面这样,在赋值的时候就可能会报错 BigDecimal[]...

zuodingquan666的博客 3285

bigdecimal js 判断等于0_BigDecimal.valueof(Double t)/(String t)的区别

先用简单的代码展示一下Java代码:上面的代码主要的区别在于初始化BigDecimal时形参是double、String和float的区别从上面可以看到,当double 和 float 时,实际保存的值并不是是准确的0.99,这是为什么呢大致的原因是: BigDecimal(double val)将会把double型二进制浮点型值精确的转换成十进制的BigDecimal。 你可能认为java中用n...

weixin_30874365的博客 210

BigDecimal运算

原文链接:https://blog.csdn.net/haiyinshushe/article/details/82721234 Javajava.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double...

LeetCode:Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum 823

判断BigDecimal是否为null

开发中的小总结 在开发中如果对BigDecima做赋值操作的时候就需要事先对BigDecima做是否为null的校验不然程序会报空指针异常,

weixin_43167662的博客 3万+

BigDecimal totalAmount = BigDecimal.ZERO;

Java 中,“bigdecimal totalamount = bigdecimal.zero;” 这样的代码通常用于初始化一个 BigDecimal 类型的变量 totalamount 为 0。BigDecimalJava 中用于精确数值计算的类,避免了浮点数计算中的精度丢失问题。在 Java 中,可以使用多种方式初始化 BigDecimal 为 0。比如使用 BigDecimal 的静态常量 ZERO:BigDecimal decimal = BigDecimal.ZERO。

weixin_57722696的博客 1015

(完整版)全国医院名录excel版(17341).xls

(完整版)全国医院名录excel版(17341).xls

上一篇: java beanlisthandler_模拟apache commons dbutils 实现自己的BeanListHandler(回调应用)
下一篇: getpriority 方法 java_int getPriority()
我是跟野兽差不了多少
博客等级 码龄10年 33粉丝 709原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值