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

相关内容

热门资讯

飞天茅台,又涨了100块,陈华... 作者:王一行 不到四个月,飞天茅台又涨价了。 加上3月31日那次涨价,今年飞天茅台的出厂价和零售价累...
银行理财收益缩水,机构集体喊话... 【大河财立方 记者 吴海舒 杨萨】“我自己买股票都没它能亏”,某社交平台上,一位网友晒出了自己购买的...
蒙商银行行长牛冠荣拟任内蒙古自... 蒙商银行行长牛冠荣拟任内蒙古自治区党委管理领导班子企业正职 人民财讯7月25日电,内蒙古自治区党委组...
首发经济破局 激活消费新动能 在昆明顺城购物中心,占地1800平方米的蜜雪冰城旗舰店人气爆棚,门口排满了前来打卡的消费者;蜡笔小新...
原创 谁... 坐在深圳南山的写字楼里往窗外看,无人机送外卖、机器人巡逻、满街的新能源车,很多外地人第一次来都会愣一...
“硬件创新基础设施”嘉立创今日... 7月24日,深圳嘉立创科技集团股份有限公司(以下简称“嘉立创”)正式启动网上网下发行申购,申购简称为...
深化产教融合 推进数智育人 哈... 7月23日,由阿里国际人工智能人才孵化中心(以下简称“阿里国际AITIC”)主办的“智启未来·数智赋...
陈春玉够“稳”,但魔法原子还“... 今年上半年,魔法原子获得了春晚的热度,但是也受到了人事和商业化的质疑。面对外界疑问,陈春玉依靠扎实的...
实物黄金和纸黄金的交易成本如何... 在黄金投资领域,实物黄金和纸黄金是较为常见的两种投资方式,而了解它们的交易成本计算方法对于投资者来说...
这些绩优股发布拟增持计划(附股... 7月以来,上市公司密集发布拟增持计划。与此同时,德明利、广钢气体、柯力传感等多家公司还发布了承诺不减...
特斯拉一周跌没18%,马斯克自... 马斯克这周不好过——特斯拉周五跌超2%,本周累跌近18%,创2022年以来最大单周跌幅;SpaceX...
原创 世... 文|江月白 编辑|江月白 近期中东局势再度掀起波澜,也门胡塞武装突然宣布封锁红海的曼德海峡,这一举...
农业农村部:乡村消费韧性持续凸... 本报记者 刘萌 7月24日,国新办举行新闻发布会介绍2026年上半年农业农村经济运行情况。农业农村部...
一杯鲜啤引爆夏夜狂欢 如东啤酒... 扬子晚报讯(记者 郭小川 通讯员 王军)如火的夏夜,怎能少了一杯清凉爽口的鲜啤?连日来,夜色中的如东...
原创 通... 时间定了,下周油价大涨!2026年汽柴油第10次上涨在即,时间将于7月31日24时准时调价,倒计时仅...
Waymo计划独立进入两地Ro... 7 月 25 日消息,据《金融时报》报道,Alphabet 旗下自动驾驶出租车企业 Waymo 在一...
日均狂赚2.39亿!宁德时代拿... 图片来源:图虫 7月24日晚,宁德时代(300750.SZ)披露2026年半年报,报告期内,公司实现...
长鑫科技下周一上市:合肥产投集... 长鑫科技下周一上市,大股东 合肥产投 都有哪些布局? 长鑫上市,合肥产投能赚多少? 作为长鑫科技发起...
ETF市场周报 | 市场回升趋... 市场回顾: 本周(2026年7月20日-7月24日),A股市场触底反弹,前4日整体走势强劲,周五略有...
美股开盘:指数涨跌不一 ,存储... 7月24日晚间,美股三大指数开盘后涨跌不一。截至发稿,标普500指数涨0.24%,道指涨0.32%,...