专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

BigDecimal你真的会用吗?

  1。BigDecimal1。1背景
  一直从事金融相关项目,所以对BigDecimal再熟悉不过了,也曾看到很多时候因为不知道、不了解或使用不当导致资损事件发生。
  所以,如果从事金融相关项目,或者在项目中涉及到金额的计算,那么你一定要花时间看看这篇文章,全面学习一下BigDecimal。1。2BigDecimal概述
  Java在java。math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。
  一般情况下,对于不需要准确计算精度的数字,可以直接使用Float和Double处理,但是Double。valueOf(String)和Float。valueOf(String)会丢失精度。所以如果需要精确计算的结果,则必须使用BigDecimal类来操作。
  BigDecimal所创建的是对象,我们不能使用传统的、、、等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。1。3为什么使用BigDecimal
  看如下代码:publicstaticvoidmain(String〔〕args)throwsException{System。out。println(0。20。1);System。out。println(0。30。1);System。out。println(0。20。1);System。out。println(0。30。1);}
  打印结果:
  为何会这样:
  原因:不论是float还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。
  根本原因:十进制值通常没有完全相同的二进制表示形式;十进制数的二进制表示形式可能不精确。只能无限接近于那个值。
  但是,在项目中,我们不可能让这种情况出现,特别是金融项目,因为涉及金额的计算都必须十分精确,否则,如果你的微信账户余额显示193。99999999999998,那是一种怎么样的体验?
  float和double为什么不精确:
  首先,计算机是只认识二进制的,即0和1,这个大家一定都知道。
  那么,所有数字,包括整数和小数,想要在计算机中存储和展示,都需要转成二进制。
  十进制整数转成二进制很简单,通常采用除2取余,逆序排列即可,如10的二进制为1010
  但是,小数的二进制如何表示呢?
  十进制小数转成二进制,一般采用乘2取整,顺序排列方法,如0。625转成二进制的表示为0。101。
  具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的整数部分为零,或者整数部分为1,此时0或1为二进制的最后一位。或者达到所要求的精度为止
  但是,并不是所有小数都能转成二进制,如0。1就不能直接用二进制表示,他的二进制是0。000110011001100一个无限循环小数
  这里我们使用乘2取整,顺序排列的方法来计算一下0。120。2取整数部分00。220。4取整数部分00。420。8取整数部分00。821。6取整数部分10。621。2取整数部分10。220。2取整数部分0(从此处又开始新的一轮循环)所以0。1的二进制为0。0001100110011无限循
  所以,计算机是没办法用二进制精确的表示0。1的。也就是说,在计算机中,很多小数没办法精确的使用二进制表示出来,这也就是为什么float和double的值并不是精确的原因了,其只是在一定精度范围内表示一个浮点数。1。4如何使用BigDecimal1。4。1初始化赋值
  方法
  类型
  描述
  publicBigDecimal(intval)
  构造函数
  int类型的值生成BigDecimal对象
  publicBigDecimal(longval)
  构造函数
  long类型的值生成BigDecimal对象
  publicBigDecimal(Stringval)
  静态方法
  String类型的值转换为BigDecimal类型
  publicstaticBigDecimalvalueOf(doubleval)
  静态方法
  double类型的值转换为BigDecimal类型
  publicstaticBigDecimalvalueOf(longval)
  静态方法
  long类型(包含int类型)的值转换为BigDecimal类型
  通常建议优先使用String构造方法。当double必须用作BigDecimal的源时,请使用Double。toString(double)转成String,然后使用String构造方法,或使用BigDecimal的静态方法valueOf:BigDecimalbnewBigDecimal(12。3);BigDecimalcBigDecimal。valueOf(7。34325);BigDecimaldnewBigDecimal(Double。toString(7。34325));System。out。println(b);System。out。println(c);System。out。println(d);
  打印结果:
  1。4。2加减乘除运算
  运算法则
  对应方法
  加法
  publicBigDecimaladd(BigDecimalvalue)
  减法
  publicBigDecimalsubtract(BigDecimalvalue)
  乘法
  publicBigDecimalmultiply(BigDecimalvalue)
  除法
  publicBigDecimalpide(BigDecimalvalue)
  代码示例:publicstaticvoidmain(String〔〕args)throwsException{System。out。println(计算加法:BigDecimal。valueOf(1。9)。add(BigDecimal。valueOf(0。2)));System。out。println(计算减法:BigDecimal。valueOf(1。9)。subtract(BigDecimal。valueOf(1。5)));System。out。println(计算乘法:BigDecimal。valueOf(1。9)。multiply(BigDecimal。valueOf(0。2)));System。out。println(计算除法:BigDecimal。valueOf(1。9)。pide(BigDecimal。valueOf(0。2)));}
  打印结果:
  注意点:BigDecimal的运算结果都是返回了一个新的BigDecimal对象,并不是在原有的对象上进行操作。使用pide除法函数除不尽,出现无线循环小数的时候,就需要使用另外精确的小数位数以及舍入模式,不然会出现报错。1。4。3保留小数及舍入模式publicBigDecimalsetScale(intnewScale,introundingMode)
  用于格式化小数的方法,第一个值表示保留几位小数,第二个值表示格式化的类型。
  8种类型如下:
  格式化类型
  描述
  ROUNDDOWN
  舍弃多余位数,如1。55会格式化为1。5,1。55会格式化为1。5
  ROUNDUP
  进位处理,如1。52会格式化为1。6,1。52会格式化为1。6
  ROUNDHALFUP
  四舍五入,如果舍弃部分。5,则进位
  ROUNDHALFDOWN
  五舍六入,如果舍弃部分。5,则进位
  ROUNDCEILING
  正无穷大方向舍入模式。如果值为正数,则与ROUNDUP模式相同;如果值为负数,则与ROUNDDOWN模式相同
  ROUNDFLOOR
  负无穷大方向舍入模式。如果值为正数,则与ROUNDDOWN模式相同;如果值为负数,则与ROUNDUP模式相同
  ROUNDUNNECESSARY
  确认值的小数位数是否与传入第一个参数(保留小数的位数)相等,如果符合则返回值,如果不符抛出异常
  ROUNDHALFEVEN
  如果舍弃部门左边的数字为奇数,则与ROUNDHALFUP模式相同,如果为偶数则与ROUNDHALFDOWN模式相同
  代码示例:publicstaticvoidmain(String〔〕args){BigDecimalaBigDecimal。valueOf(5。445);System。out。println(5。445舍弃多余位数:a。setScale(2,BigDecimal。ROUNDDOWN));System。out。println(5。445进位处理:a。setScale(2,BigDecimal。ROUNDUP));System。out。println(5。445四舍五入(舍弃部分。5,进位):a。setScale(2,BigDecimal。ROUNDHALFUP));System。out。println(5。445四舍五入(舍弃部分未。5,舍弃):a。setScale(2,BigDecimal。ROUNDHALFDOWN));System。out。println(5。446四舍五入(舍弃部分。5,进位):BigDecimal。valueOf(5。446)。setScale(2,BigDecimal。ROUNDHALFDOWN));}
  打印结果:
  1。4。4比较大小publicintcompareTo(BigDecimalval)
  BigDecimal类提供的比较值的方法,注意比较的两个值均不能为空。
  a。compareTo(b)得到结果1,0,1。
  比较结果
  描述
  1hra大于b
  0hra等于b
  1
  a小于b
  代码示例:publicstaticvoidmain(String〔〕args){BigDecimalaBigDecimal。valueOf(1);BigDecimalbBigDecimal。valueOf(2);BigDecimalcBigDecimal。valueOf(1);BigDecimaldBigDecimal。ZERO;System。out。println(1和2比较结果:a。compareTo(b));System。out。println(1和1比较结果:a。compareTo(c));System。out。println(1和0比较判断:(a。compareTo(d)0));}
  打印结果:
  注意:实际业务中,不会单纯的比较谁打谁小,而是类似于第三条去判断一个布尔值。1。4。5其他方法及常量
  代码
  类型
  描述
  BigDecimal。ZERO
  常量
  初始化一个为0的BigDecimal对象
  BigDecimal。ONE
  常量
  初始化一个为1的BigDecimal对象
  BigDecimal。TEN
  常量
  初始化一个为10的BigDecimal对象
  publicBigDecimalabs()
  方法
  求绝对值,不管正数还是负数,都得到正数
  publicBigDecimalnegate()
  方法
  求相反数,正变负,负变正
  publicBigDecimalpow(intn)
  方法
  求乘方,如BigDecimal。valueOf(2)。pow(3)的值为8
  publicBigDecimalmax(BigDecimalval)
  方法
  两值比较,返回最大值
  publicBigDecimalmin(BigDecimalval)
  方法
  两值比较,返回最小值1。5BigDecimal的4个坑
  在使用BigDecimal时,有4种使用场景下的坑,你一定要了解一下,如果使用不当,必定很惨。掌握这些案例,当别人写出有坑的代码,你也能够一眼识别出来,大牛就是这么练成的。1。5。1浮点类型的坑
  在学习了解BigDecimal的坑之前,先来说一个老生常谈的问题:如果使用Float、Double等浮点类型进行计算时,有可能得到的是一个近似值,而不是精确的值。
  比如下面的代码:Testpublicvoidtest0(){floata1;floatb0。9f;System。out。println(ab);}
  结果是多少?0。1吗?不是,执行上面代码执行的结果是0。100000024。之所以产生这样的结果,是因为0。1的二进制表示是无限循环的。由于计算机的资源是有限的,所以是没办法用二进制精确的表示0。1,只能用近似值来表示,就是在有限的精度情况下,最大化接近0。1的二进制数,于是就会造成精度缺失的情况。
  那么,BigDecimal就一定能避免上述的浮点问题吗?来看下面的示例:Testpublicvoidtest1(){BigDecimalanewBigDecimal(0。01);BigDecimalbBigDecimal。valueOf(0。01);System。out。println(aa);System。out。println(bb);}
  结果:a0。01000000000000000020816681711721685132943093776702880859375b0。01
  上面的实例说明,即便是使用BigDecimal,结果依旧会出现精度问题。这就涉及到创建BigDecimal对象时,如果有初始值,是采用newBigDecimal的形式,还是通过BigDecimalvalueOf方法了。
  之所以会出现上述现象,是因为newBigDecimal时,传入的0。1已经是浮点类型了,鉴于上面说的这个值只是近似值,在使用newBigDecimal时就把这个近似值完整的保留下来了。
  而BigDecimalvalueOf则不同,它的源码实现如下:publicstaticBigDecimalvalueOf(doubleval){Reminder:azerodoublereturns0。0,sowecannotfastpathtousetheconstantZERO。Thismightbeimportantenoughtojustifyafactoryapproach,acache,orafewprivateconstants,later。returnnewBigDecimal(Double。toString(val));}
  在valueOf内部,使用DoubletoString方法,将浮点类型的值转换成了字符串,因此就不存在精度丢失问题了。
  此时就得出一个基本的结论:第一,在使用BigDecimal构造函数时,尽量传递字符串而非浮点类型;第二,如果无法满足第一条,则可采用BigDecimalvalueOf方法来构造初始化值。1。5。2浮点精度的坑
  如果比较两个BigDecimal的值是否相等,你会如何比较?使用equals方法还是compareTo方法呢?
  先来看一个示例:Testpublicvoidtest2(){BigDecimalanewBigDecimal(0。01);BigDecimalbnewBigDecimal(0。010);System。out。println(a。equals(b));System。out。println(a。compareTo(b));}Overridepublicbooleanequals(Objectx){if(!(xinstanceofBigDecimal))returnfalse;BigDecimalxDec(BigDecimal)x;if(xthis)returntrue;if(scale!xDec。scale)returnfalse;longsthis。intCompact;longxsxDec。intCompact;if(s!INFLATED){if(xsINFLATED)xscompactValFor(xDec。intVal);returnxss;}elseif(xs!INFLATED)returnxscompactValFor(this。intVal);returnthis。inflated()。equals(xDec。inflated());}
  equals方法不仅比较了值是否相等,还比较了精度是否相同。上述示例中,由于两者的精度不同,所以equals方法的结果当然是false了。而compareTo方法实现了Comparable接口,真正比较的是值的大小,返回的值为1(小于),0(等于),1(大于)。
  基本结论:通常情况,如果比较两个BigDecimal值的大小,采用其实现的compareTo方法;如果严格限制精度的比较,那么则可考虑使用equals方法。1。5。3设置精度的坑
  在项目中看到好多同学通过BigDecimal进行计算时不设置计算结果的精度和舍入模式,真是着急人,虽然大多数情况下不会出现什么问题。但下面的场景就不一定了:Testpublicvoidtest3(){BigDecimalanewBigDecimal(1。0);BigDecimalbnewBigDecimal(3。0);a。pide(b);}
  执行上述代码的结果是什么?ArithmeticException异常!
  总结:如果在除法(pide)运算过程中,如果商是一个无限小数(0。333),而操作的结果预期是一个精确的数字,那么将会抛出ArithmeticException异常。
  此时,只需在使用pide方法时指定结果的精度即可:Testpublicvoidtest3(){BigDecimalanewBigDecimal(1。0);BigDecimalbnewBigDecimal(3。0);BigDecimalca。pide(b,2,RoundingMode。HALFUP);System。out。println(c);}
  执行上述代码,输入结果为0。33。
  基本结论:在使用BigDecimal进行(所有)运算时,一定要明确指定精度和舍入模式。1。5。4三种字符串输出的坑
  当使用BigDecimal之后,需要转换成String类型,你是如何操作的?直接toString?
  先来看看下面的代码:Testpublicvoidtest4(){BigDecimalaBigDecimal。valueOf(35634535255456719。22345634534124578902);System。out。println(a。toString());}
  执行的结果是上述对应的值吗?并不是:3。563453525545672E16
  也就是说,本来想打印字符串的,结果打印出来的是科学计数法的值。
  这里我们需要了解BigDecimal转换字符串的三个方法toPlainString():不使用任何科学计数法;toString():在必要的时候使用科学计数法;toEngineeringString():在必要的时候使用工程计数法。类似于科学计数法,只不过指数的幂都是3的倍数,这样方便工程上的应用,因为在很多单位转换的时候都是103;
  基本结论:根据数据结果展示格式不同,采用不同的字符串输出方法,通常使用比较多的方法为toPlainString()。1。5。5NumberFormat类
  另外,NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。
  使用示例如下:NumberFormatcurrencyNumberFormat。getCurrencyInstance();建立货币格式化引用NumberFormatpercentNumberFormat。getPercentInstance();建立百分比格式化引用percent。setMaximumFractionDigits(3);百分比小数点最多3位BigDecimalloanAmountnewBigDecimal(15000。48);金额BigDecimalinterestRatenewBigDecimal(0。008);利率BigDecimalinterestloanAmount。multiply(interestRate);相乘System。out。println(金额:currency。format(loanAmount));System。out。println(利率:percent。format(interestRate));System。out。println(利息:currency。format(interest));
  输出结果如下:金额:15,000。48利率:0。8利息:120。00

德甲门兴vs斯图加特,客队状态稀烂,为什么还是看好门兴无胜?昨日回顾皇社01曼联感谢滕子让我看到了我在游戏的操作本场比赛尾声时刻,马奎尔替补出场换下加纳乔,和C罗在场上搭档前锋。阿森纳10苏黎世这个10的代价有点大啊,20的话也就不用上富安特斯拉起诉蔡老板终胜诉,10万赔偿是不是有点少了?特斯拉总算是出了一口胸中的恶气。日前,特斯拉起诉蔡甲(蔡老板)侵犯其名誉权并索赔500万元一案,法院判决结果出炉蔡甲向特斯拉公开道歉,并赔偿特斯拉10万元。根据法院判决,蔡老板在抖荣耀Magic3Pro大方退市包括12G512G在内,全部降2730元荣耀这个品牌虽然现在和华为不是一家,但内行人也都知道,其实在当初荣耀独立的时候,华为给了他很多技术员工,独立之后荣耀之所以能快速发展恢复销量,就多亏了有这一批曾经的华为员工存在。大小米强制更新MIUI13,玩家不干了凭啥替我选择?小米强制更新如果说硬件是的骨架肌肉,那么UI就是手机的血液灵魂。对于小米来说,MIUI就是串联起手机与各类智能生态硬件的灵魂,最新的MIUI13已经开始推送了,但是近期有不少玩家表小米有品上新木星黎明捍卫者发射器一次地狱级难度的搭建冒险作为一名积木爱好者表示,玩了这么多年的搭建,真心没碰到几个难度的产品,不过,最近听说小米有品上架了一款地狱级难度的积木产品,着实勾起了我的好奇心,是什么样的积木?竟然敢说自己的产品一双UGG老棉鞋,如何成为辣妹冬天里的一把火?原创嘴嘴来源Vista氢商业UGG又把丑鞋整出了新的高度。要么底子加厚厚厚厚,新版矮子乐冠军没有mini雪地靴很难让人信服要么勾一圈毛线边,不知道的还以为把我奶奶压箱底的棉拖鞋偷了为你情根深种,想你直到永远红尘偌大,人海茫茫,能于人海深处逢君,当是这世间最美丽的缘分。遇见你的那种感觉,就像在萧瑟的冬天邂逅了花开十亩的惊艳。与你执手的感觉,就像在薄凉的时光中邂逅了阳光万顷的温暖。感谢你那些激励着我们继续前行的句子,送给依然在坚持的你公众号落落精进馆图网络1。活着就要记住,人生最痛苦最绝望的那一刻是最难熬的时候,但不是生命结束的最后一刻,熬过去就会开始一个重要的转折,开始一个新的辉煌历程。2。当人生经历一段困难马丁靴失宠了!今年流行的是乐福鞋,配裤子高级配裙子减龄服装对于形象的提升,可以顷刻间让人为你着迷。这或许也是我们执着于提升造型品味的原因。从上衣裤装裙装到鞋子,每一个选择细节,都会影响到最终的造型风格。所以,聪明的女生穿衣,从挑选单品Elasticsearch高级检索检索原理每一个Index都被分成两个区,一个是索引区,一个是元数据区(文档区)。当一个Document存储进入Index时,存放的位置是Index的文档区,ES会给该Documen沂蒙红色崮事微记录送子送郎出征前线,抱犊崮下军民情深枣庄市山亭区以东南二十公里,山浪峰涛,层层叠叠。群山环抱下,一峰突起,如擎天玉柱直插霄汉,这是主峰抱犊崮。抱犊崮是崮形山的典型代表,山顶平整四周峭壁陡立,雄伟而险峻。翻开辞海,崮释
科莫多巨蜥的毒液到底有多可怕?2009年,一名31岁的渔民安瓦尔,在印尼科莫多岛上采摘水果,结果不小心从水果树上掉了下来,刚好踩到了一只巨型蜥蜴,蜥蜴瞬间就朝他扑了过去,咬住了他的腿,之后又咬住了他的手臂,身体武汉未来的房价会涨到100000元平米吗?这个问题的答案是肯定的!以目前的趋势,未来武汉房价必然达到10万的水平,只是时间长短的问题。2010年至2017年,短短七年间,武汉的房价已经翻了3番,目前,武汉部分高端楼盘如洞庭兰州青白石片区,中央公园怎么样?兰州北拓的黄金区域,目前基础交通还跟不上建设需要,交通滞后可能会成为十四五期间兰州青白石片区发展的的最大障碍!不过就兰州地理位置和城区格局而言,青白石片区是离主城区最近的待开发区域农民为什么不在国家统计失业范围之内?中国有四个儿子,大儿子叫工人,二儿子叫子弟兵,三儿子叫公务员,四儿子叫农民,所以四儿子就没有纳入统计失业包括养老金范围,因为四儿子有金山银山还有三分地。农民有土地,这是农民可以赖以农村成立社区是什么意思?很多农村驻有村委会办公室,同时也驻有社区管理委员会办公室,特别是在城市郊区的农村和街道的农村都同时设立了村委会和社区管理委员会,很多人弄不明白是怎么回事。那农村成立社区是什么意思呢农村里的剩男,为何一剩再剩呢?到底是什么原因?男女比例失调。计划生育只要一个孩子时,受封建思想影响,都拚命要男孩,等他们长大了,很难找到媳妇。一,农村姑娘远嫁,二,女孩见少,三,彩礼高,四,剩男挣钱少。我就一大龄剩男!个人亲身抖音付费直播试水,看直播要给钱了?我们应该如何思考?使劲收,最好是家人们看的话,一分钟100块钱。毕竟粉丝听话的很。毕竟人设都设计好了打PK,卖货摆错价格,怒亏2个亿回馈粉丝。没事就怼工厂,怼员工反正就是赔钱回馈粉丝。赔完还得补交税马上就要退休了,退休工资才3650元太少了,怎么办?3600不少了。我企业工龄32年,退休时退休金只有2200,涨了这么多年还不到3000。知足常乐吧!如果身体不好,这些钱也够生活了,如果身体还可以,就找一些力所能及的工作,打打工补南宁五象新区未来的发展潜力很大吗?五象新区无法成为国家级新区!!!目前看来,五象新区的潜力也就这样了。我们对比一下贵阳的贵安新区,贵安新区的面积是1700平方公里,由贵阳市的郊区和安顺市合并得来。是全国第8个国家级如果把三峡大坝加高10米,截留更多的洪水,可行吗?我国的三峡大坝,作为当今世界上最大的水利枢纽工程,位于湖北省宜昌市上游,距下游葛洲坝水电站38公里,三峡大坝全长2309米高185米,呈梯形形状,集发电旅游航运调控洪水于一身。三峡大家有经历过亲人去世吗?是怎样走出痛苦和想念的?2018年9月1日下午3点8分,我的妻子在医院里停止了呼吸。她的眼睛没有闭上,我流着泪,帮她合上了双眼。我永远失去了我最亲近的爱人,孩子永远的失去了妈妈。一位好妻子,好女儿,好姑妈
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网