BigDecimal使用
admin
2024-03-22 05:18:11
0

BigDecimal使用

介绍

​ Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。

为啥使用BigDecimal

​ 小数转二进制很大的可能会出现无限循环或者转成二进制之后数据特别长,而计算机中对于小数的存储按照IEEE754标准只会保留一定的二进制位数,按精度不同,保留的位数不同。按照保留的二进制位数 float型变量仅能接收实数型常量的6-7位有效数字。 double型变量能接收实数型常量的15-16位有效数字。 这样的精度对于部分场合是不适合的,所以我们使用BigDecimal.

/** 精度损失问题,3490593 转二进制为  1101010100001100100001  0.9 转二进制位  1110.....省略,最终得到1101010100001100100001.1110* 舍去到21位的时候,最后面的1进行进1处理,所以得到尾数位为101010000110010001000,最终输出为3490594.0* */
System.out.println(3490593.9f);
// 输出为 3490594.0 /**
* 0.6 转二进制,是1001100110011001100110011.......,一直循环,用单精度表示 0 01111110 00110011001100110011010* 尾数00110011001100110011010,是1001100110011001100110011 首位1作为隐藏位后,第24位做了进1处理。* 所以用浮点数存放的0.6比 0.6要大。用1.0 - 0.6f 得到的数据比0.4要小* 至于为啥0.6f 直接输出还是0.6,这个java这边对float输出是是做了转换的,(具体我也不清楚,c++源码了)
* */
System.out.println(Integer.toBinaryString(Float.floatToIntBits(0.6f)));
System.out.println(1.0f-0.6f);
System.out.println(0.6f);
// 输出为
111111000110011001100110011010
0.39999998
0.6

​ 简而言之,你将一个数定义为float和double的时候,就已经产生了精度损失。

int和float计算问题

// int类型计算会对结果进行截取,小数点后就不要了
System.out.println(3/4);// 输出 0
// 所以一般进行科学计算会使用float和double类型,/*** 下面程序说明了 float 有6-7位有效数字,double有 15-16位有效数字,* 有效数字不包含最后一位,原因是小数转浮点数,尾数只保存一定的位数,超过后进行舍去或进1* 有效数字不包含最前面的0,原因是小数转浮点数,如果前面都是0,尾数左移一位,阶码 -1。。。* */System.out.println(1/3.0f);System.out.println(1/30.0f);System.out.println(1/300.0f);System.out.println(1/0.3f);System.out.println(1/3.0);System.out.println(1/30.0);System.out.println(1/300.0);System.out.println(1/0.3);
// 输出
0.33333334
0.033333335
0.0033333334
3.3333333
0.3333333333333333
0.03333333333333333
0.0033333333333333335
3.3333333333333335/*** 浮点型转字符串按如下方法,这里要说明的是按照这种方法保留一定小数位是按四舍五入的规则来的* 还有你可以通过float和double的包装类将数字型字符串转成浮点型* */String d1 = String.format("%.2f", 0.335);String d2 = String.format("%.2f", 0.334);System.out.println(d1);System.out.println(d2);Float f1 = Float.valueOf(d1);Float f2 = Float.valueOf(d2);System.out.println(f1);System.out.println(f2);    

BigDecimal计算

BigDecimal和浮点型互转

        /*** 将浮点型转BigDecimal* */float f = 0.6f;BigDecimal a = new BigDecimal("0.6");// 这个方法内部是这么操作的 new BigDecimal(Double.toString(val));BigDecimal b = BigDecimal.valueOf(f);// 用下面的方法获取的BigDecimal对象,存放的数字是不准确的,不建议使用,你可以理解一个数定义为浮点数就产生了精度损失,变的不准确,你在构建BigDecimal时给的就不是一个准确的数字BigDecimal c = new BigDecimal(0.6);System.out.println(a);System.out.println(c);
// 输出
0.6
0.59999999999999997779553950749686919152736663818359375/*** 将BigDecimal转浮点数,或者你只需要数字的整数部分* */double v = a.doubleValue();int i = a.intValue();System.out.println(v);System.out.println(i);    
// 输出
0.6
0

BigDecimal运算

        /*** BigDecimal的加减乘除,计算一般需要制定保留多少位小数,特别是除法,否则遇到无限循环小数,会抛出异常* java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.* BigDecimal的加减乘除方法有很多的重载方法,此处介绍比较常用的方法* */BigDecimal a = new BigDecimal("0.1");BigDecimal b = new BigDecimal("0.3");BigDecimal c = new BigDecimal("-0.3");// BigDecimal divide = a.divide(b); --比如这样就会抛出异常// 除法, a/b  -- b为被数,2为保留的小数位,RoundingMode.HALF_UP表示进行四舍五入操作BigDecimal divide = a.divide(b, 2, RoundingMode.HALF_UP); // 0.33// 乘法BigDecimal multiply = a.multiply(b); // 0.03// 加法BigDecimal add = a.add(b); // 0.4// 减法BigDecimal subtract = a.subtract(b); // -0.2// 求绝对值BigDecimal abs = c.abs(); // 0.1//求大小BigDecimal max = a.max(b); // 0.3BigDecimal min = a.min(b); // 0.1// 求商BigDecimal bigDecimal = a.divideToIntegralValue(b); //0// 求余BigDecimal remainder = a.remainder(b); //0.1// 返回商和余数的数组BigDecimal[] bigDecimals = a.divideAndRemainder(b); // [0, 0.1]// 返回当前BigDecimal对象BigDecimal plus = a.plus(); // 0.1// 返回当前数的负数BigDecimal negate = a.negate(); // -0.1// a的幂次方BigDecimal pow = a.pow(2); // 0.01// 返回a的精度int precision = a.precision(); // 1// 小数点左移 1位,右移的方法不介绍BigDecimal movePointLeft = a.movePointLeft(1); // 0.01//https://blog.csdn.net/cumubi7453/article/details/107798930 大概就是-132.45 --》 -12345  0.0 --》 0   0.12 --> 12BigInteger bigInteger = a.unscaledValue(); // 1

BigDecimal保留小数位数和舍入模式

        /*** 上面的运算除了除法, 其他的都没有指定舍入模式,和保留位数,此处介绍设置保留位数和舍入模式的方法* */BigDecimal b = new BigDecimal("0.3333333333");// 保留两位,四舍五入BigDecimal bigDecimal = b.setScale(2,RoundingMode.HALF_UP);

舍入模式RoundingMode

// RoundingMode 枚举类存放了BigDecimal的舍入模式, 进入其中,可以通过注释了解舍入模式的详情
UP(BigDecimal.ROUND_UP) //舍入远离零的舍入模式
DOWN(BigDecimal.ROUND_DOWN) //接近零的舍入模式。
CEILING(BigDecimal.ROUND_CEILING)  //接近正无穷大的舍入模式   
FLOOR(BigDecimal.ROUND_FLOOR) //  接近负无穷大的舍入模式
HALF_UP(BigDecimal.ROUND_HALF_UP) //向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式  (四舍五入)
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN) // 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式(五舍六入)
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN) //向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入UNNECESSARY(BigDecimal.ROUND_UNNECESSARY) //断言请求的操作具有精确的结果,因此不需要舍入,如果不成功,抛出异常  比如0.333保留2位,抛异常

MathContext入参

/*** BigDecimal的部分方法中有MathContext对象作为参数传入* MathContext对象用于指定计算后数据的保留的有效数字Precision,这里的有效数字和保留小数点后多少位是有区别的,可以通过下面的示例看出区别* 还可以指定数据的舍入模式
* */
BigDecimal b = new BigDecimal("0.00333333333");
MathContext mathContext = new MathContext(2, RoundingMode.HALF_UP);
//和上面的的效果等同,不设置舍入模式,默认舍入模式为RoundingMode.HALF_UP
MathContext mathContext1 = new MathContext(2);
BigDecimal bigDecimal = b.setScale(2,RoundingMode.HALF_UP); //0.00
BigDecimal plus = b.plus(mathContext1);//0.0033

相关内容

热门资讯

贷款也“拼团” 银行抢单忙 购物能“拼团”,贷款也能! 近日,一场“拼团融资”的银企对接活动在省工业和信息化厅拉开帷幕。 “贷款...
逛花展、赶市集、嗨直播!202... 5月23日 “2026北京直播电商购物月” 在丰台区丽泽金融商务区·2026北京国际花展 正式拉开帷...
2026中关村毕业季|AI“吃... “上帝会掷骰子吗?” 在联想未来中心的“与智者同场”展区,一位海淀学子对着屏幕问道。 爱因斯坦微微前...
原创 今... 今日为5月23日,国际现货黄金价格在4500美元/盎司整数关口附近徘徊不前,日内最低触及4480美元...
三连亏后变为“无主”状态,农尚... 从吴亮手中接盘农尚环境(300536)不足三年后,林峰如今让出了公司控制权,上市公司进入“无主”状态...
55岁湖南女首富出手!豪掷13... 快科技5月24日消息,与马斯克、库克并肩而坐,刚参加完国宴的湖南女首富周群飞就买了家上市企业。 近日...
外资加仓A股,岂是跟风这么简单... 熬过忙碌的交易日,在周末安静时段,理清接下来布局方向。本篇为大家准备了5条要闻,涵盖市场动态、行业变...
原创 俄... 在全球能源的残酷牌桌上,手里攥着石油,腰杆子才能硬气。长期以来,中东的沙漠、俄罗斯的冰原、美国的页岩...
喜力啤酒有产品将涨价,华润啤酒... 来源:红星新闻 红星资本局5月22日消息,今日,红星资本局从雪花啤酒(厦门)有限公司、华润啤酒方面获...
原创 金... 心理预期调整刻不容缓,五月二十二日,黄金价格或将重现十五年前的历史性低迷。 近期若您密切关注着黄金市...
原创 马... 埃隆·马斯克如果能让SpaceX实现“科幻小说”级别的目标,他可能获得1万亿美元的收入。 埃隆·马斯...
涨涨涨!放开限制、可加杠杆!这... 韩国股市站在风口上! 据最新消息,为吸引更多海外资金进入股市,韩国政府计划放开限制,允许境外投资者直...
下周9家上会丨科创板首单IPO... IPO及再融资上会预告 据交易所官网审核动态信息,下周(5.25-5.29)IPO上会审核6家企业,...
富途、老虎市值蒸发1/4!或被... 来源:金融时报 5月22日,中国证监会宣布依法对Tiger Brokers (NZ) Limited...
马爸爸的好兄弟钱多多搞了杀猪盘... *此图由AI生成 作者| 史大郎&猫哥 来源| 是史大郎&大猫财经Pro 上周四,港股经纬天地大崩盘...
原创 壳... 编辑:XL 国际能源圈最近炸开了锅,壳牌这家百年石油巨头在2026年3月与委内瑞拉政府正式签署多项油...
存储热潮愈演愈烈!奖金拿到手软... 财联社5月24日讯(编辑 卞纯)在席卷全球的存储芯片热潮中,韩国“存储芯片双雄”SK海力士和三星无疑...
揽牌、合作、生态,跨境支付头部... 近日,国内头部跨境支付机构密集落地海外重要布局,一方面,连连数字、PingPong两家公司相继在中东...
原创 帮... 老铁们,周末好!我是帮主郑重。刚扫了一眼下周的财经日历,好家伙,事件一个接一个,堪称“消息面轰炸周”...
海南省住建厅与中国石化海南石油... 5月22日,中国石化海南石油分公司代表、党委书记李新强、总经理蔡文东一行赴海南省住建厅拜访交流。省住...