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

相关内容

热门资讯

想找个中立的人太难:马斯克推特... IT之家 2 月 26 日消息,很少有高管能像埃隆 · 马斯克那样招致如此多的争议,这位特斯拉掌门人...
京东、中兴、大疆等19家企业总... 深圳商报·读创客户端记者曹欣 新春伊始,深圳湾超级总部基地(以下简称 “深超总”)建设全面提速,京东...
压岁钱遇上理财,有儿童专属储蓄... 作者:张昕迎 编辑:周梦梅 编者按:拼车返乡、拼单买年货,今年过年,你“拼”了吗?当Z世代主导春节,...
高盛谈AI交易:“AI基建”的... 当AI资本开支越冲越猛、估值越来越贵时,高盛提醒市场:真正的风险,往往出现在“增速开始放慢”的那一刻...
楼市新信号,二手房业主不愿卖房... 作者:千寻 01 2026开年以来,全国的二手房市场出现了新变化,二手房业主们不愿意继续割肉卖房了。...
原创 券... 券商拉盘指数走强!盘面暗藏背离,老股民直呼心慌 炒股的人都懂,A股最让人琢磨不透的,不是单边下跌,而...
又一家居企业冲击港股上市,20... 群核科技向港交所主板递交上市申请,摩根大通和建银国际担任联席保荐人。 最新数据显示,2025年,公司...
中国铁建重工集团股份有限公司2... 本公司董事会及全体董事保证本公告内容不存在任何虚假记载、误导性陈述或者重大遗漏,并对其内容的真实性、...
原创 松... 时光倒流至上世纪九十年代,那是日本电池工业的辉煌岁月。 1991年,索尼发布了人类历史上第一款商用锂...
自变量机器人一个月内又完成数亿... 投资界2月26日消息,据企查查,自变量机器人(X Square Robot)完成数亿元新一轮融资,本...
原创 2... 内容提要 2026年1月,货币市场日均交易量及余额均增加,主要回购利率走势分化,大型商业银行日均净融...
电池概念股走低,多只电池相关E... 电池概念股走低,阳光电源、宁德时代、亿纬锂能跌超4%。 受盘面影响,多只电池相关ETF跌超2%。 ...
构建“国际化、法治化、市场化”... 在当前全球科技竞争日益激烈的背景下,炒菜机器人行业作为新兴领域正展现出巨大的发展潜力。以东莞市山智智...
环渤海动力煤价格指数685元/... 上证报中国证券网讯(记者 王文嫣)2月25日,秦皇岛煤炭网发布最新一期环渤海动力煤价格指数,本报告期...
STARTRADER:摩根大通... 2月25日,摩根大通发布最新贵金属展望报告,宣布将黄金长期价格预期上调至4500美元/盎司,同时重申...
鼎泰高科晋级10倍股 人民财讯2月25日电,2月25日,鼎泰高科(301377)午后股价大涨,盘中一度涨超15%,收盘涨幅...
恒丰银行股权0.7元无人接盘,... 【文/羽扇观金工作室】 3月7日,一笔挂牌起拍价2660万元,3800万股的恒丰银行股权将在阿里资...
中国将印度告上WTO 文︱陆弃 从瑞士日内瓦那幢灰色会议楼里传出的消息,往往代表着一种秩序在悄然发生断裂。2月24日,世界...