Java 大数值类型执行精确计算
简介
如果基本的整数和浮点数精度不能够满足需求,那么可以使用 java.math 包下两个很有用的类:BigInteger 和 BigDecimal。这两个类可以处理包含任意长度数字序列的数值,BigInteger 实现了任意精度的整数运算,BigDecimal 实现了任意精度的浮点数运算。BigDecimal 由于舍入模式的存在,使得这个类用起来比 BigInteger 要复杂。
BigInteger
Java中long型为最大整数类型,对于超过long型的数据如何去表示呢。在Java的世界中,超过long型的整数已经不能被称为整数了,它们被封装成BigInteger对象。在BigInteger类中,实现四则运算都是方法来实现,并不是采用运算符。
构造方法
通过看源码可以知道有6种构造方法,没有无参构造方法,其中比较常用的是第一个。
public BigInteger(String val) {
this(val, 10);
}
基本运算
@Test
public void bigIntegerTest(){ BigInteger big1 = new BigInteger("18");
BigInteger big2 = new BigInteger("5"); //加法
BigInteger bigAdd = big1.add(big2);
System.out.println(bigAdd); //减法
BigInteger bigSub = big1.subtract(big2);
System.out.println(bigSub); //乘法
BigInteger bigMul = big1.multiply(big2);
System.out.println(bigMul); //除法
//如果两数相除为小数,直接舍去小数部分,保留整数部分
BigInteger bigDiv = big1.divide(big2);
System.out.println(bigDiv); BigInteger big3 = new BigInteger("-5");
//绝对值
BigInteger bigAbs = big3.abs();
System.out.println(bigAbs); //次方
BigInteger bigPow = big3.pow(3);
System.out.println(bigPow); //比较,返回两个数中的最大值
BigInteger bigMax = big1.max(big2);
System.out.println(bigMax); //比较,返回两个数中的最小数
BigInteger bigMin = big1.min(big2);
System.out.println(bigMin); }
BigDecimal
double和float类型在运算中很容易丢失精度,造成运算结果的不准确,Java提供我们BigDecimal类可以实现浮点数据的高精度运算。
RoundingMode
舍入模式:通过源码阅读可知,RoundingMode类中的舍入模式和BigDecimal类中的舍入模式是一样的,选择哪种都行,比如
RoundingMode.*
相当于
BigDecimal.ROUND_*
这里以枚举RoundingMode中的舍入模式简单介绍下。这个enum 是打算用来替代 BigDecimal中的舍入模式常量。
UP
远离零方向舍入。始终对非零舍弃部分前面的数字加 1。注意,此舍入模式始终不会减少计算值的绝对值。
DOWN
向零方向舍入。从不对舍弃部分前面的数字加 1(即截尾)。注意,此舍入模式始终不会增加计算值的绝对值。
CEILING
向正无限大方向舍入。如果结果为正,则舍入行为类似于 RoundingMode.UP;如果结果为负,则舍入行为类似于 RoundingMode.DOWN。注意,此舍入模式始终不会减少计算值。
FLOOR
向负无限大方向舍入。如果结果为正,则舍入行为类似于 RoundingMode.DOWN;如果结果为负,则舍入行为类似于 RoundingMode.UP。注意,此舍入模式始终不会增加计算值。
HALF_UP
向最接近数字方向舍入。如果与两个相邻数字的距离相等,则向上舍入。即:如果被舍弃部分 >= 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同 RoundingMode.DOWN。
注意,此舍入模式就是通常学校里讲的四舍五入。
HALF_DOWN
向最接近数字方向舍入。如果与两个相邻数字的距离相等,则向下舍入。即:如果被舍弃部分 > 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同 RoundingMode.DOWN。
HALF_EVEN
向最接近数字方向舍入。如果与两个相邻数字的距离相等,则向相邻的偶数舍入。即:如果舍弃部分左边的数字为奇数,则舍入行为同 RoundingMode.HALF_UP;如果为偶数,则舍入行为同 RoundingMode.HALF_DOWN。
注意,在重复进行一系列计算时,此舍入模式可以在统计上将累加错误减到最小。此舍入模式也称为“银行家舍入法”,主要在美国使用。此舍入模式类似于 Java 中对 float 和 double 算法使用的舍入策略。
UNNECESSARY
用于断言的舍入模式,请求的操作具有精确的结果,不需要进行舍入。如果对生成精确结果的操作指定此舍入模式,则抛出 ArithmeticException。
MathContext
RoundingMode 是舍入模式的抽象描述,仅仅描述了舍入的规则,但是运算中还有一些其他的规则,比如:保留几位有效数字?
MathContext 则是针对于计算的更进一步抽象,是封装上下文设置的不可变对象,它描述数字运算符的某些规则。拥有两个属性。
构造方法
构造一个新的 MathContext,它具有指定的精度和舍入模式
MathContext(int setPrecision, RoundingMode setRoundingMode)
构造一个新的 MathContext,它具有指定的精度和 HALF_UP 舍入模式
MathContext(int setPrecision)
注意:该字符串的格式必须与 toString() 方法生成的字符串的格式相同,不可以随便写!
MathContext(String val)
public java.lang.String toString() {
return "precision=" + precision + " " +
"roundingMode=" + roundingMode.toString();
}
静态对象
MathContext 内置了几个静态对象供我们使用
UNLIMITED
其设置具有无限精度算法所需值的 MathContext 对象
public static final MathContext UNLIMITED = new MathContext(0, RoundingMode.HALF_UP);
DECIMAL32
其精度设置与 IEEE 754R Decimal32 格式(即 7 个数字)匹配,舍入模式为 HALF_EVEN,这是 IEEE 754R 的默认舍入模式
public static final MathContext DECIMAL32 = new MathContext(7, RoundingMode.HALF_EVEN);
DECIMAL64
其精度设置与 IEEE 754R Decimal64 格式(即 16 个数字)匹配,舍入模式为 HALF_EVEN,这是 IEEE 754R 的默认舍入模式
public static final MathContext DECIMAL64 = new MathContext(16, RoundingMode.HALF_EVEN);
DECIMAL128
其精度设置与 IEEE 754R Decimal128 格式(即 34 个数字)匹配,舍入模式为 HALF_EVEN,这是 IEEE 754R 的默认舍入模式
public static final MathContext DECIMAL128 = new MathContext(34, RoundingMode.HALF_EVEN);
示例代码
@Test
public void bigDecimalTest(){ BigDecimal big1 = new BigDecimal("10.55");
BigDecimal big2 = new BigDecimal("0.56"); //指定精度和舍入模式
//四舍五入保留三个数字
MathContext mathContext = new MathContext(3, RoundingMode.HALF_UP); //加法
BigDecimal bigAdd = big1.add(big2);
System.out.println(bigAdd);//11.11
BigDecimal bigAdd1 = big1.add(big2, mathContext);
System.out.println(bigAdd1);//11.1 //减法
BigDecimal bigSub = big1.subtract(big2);
System.out.println(bigSub);//9.99
BigDecimal bigSub1 = big1.subtract(big2, mathContext);
System.out.println(bigSub1);//9.99 //乘法
BigDecimal bigMul = big1.multiply(big2);
System.out.println(bigMul);//5.9080
BigDecimal bigMul1 = big1.multiply(big2, mathContext);
System.out.println(bigMul1);//5.91 //除法
//注意如果除不尽,则会出现java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
//BigDecimal bigDiv = big1.divide(big2);
//System.out.println(bigDiv);
//指定保留数字位数和舍入模式
BigDecimal bigDiv1 = big1.divide(big2, mathContext);
System.out.println(bigDiv1);//18.8
//指定保留小数位数和舍入模式
BigDecimal bigDiv2 = big1.divide(big2, 2, RoundingMode.HALF_UP);
System.out.println(bigDiv2);//18.84 }
注意事项
参考博客:https://blog.csdn.net/ugg/article/details/8213666
1、尽量避免传递double类型,有可能话,尽量使用int和String类型。
直接传double类型的话,比如浮点型0.6,放入BigDecimal中就成了
0.59999999999999997779553950749686919152736663818359375,从而会造成计算结果错误。
2、做乘除计算时,一定要设置精度和保留小数点位数。
不设置的话,如果结果是一个无限循环小数的话,会抛出异常。
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
3、BigDecimal计算时,单独放到try catch内。
4、MathContext 中的 precision 是保留数字的位数, BigDecimal 中的 scale 保留小数的位数。是不一样的。
Java 大数值类型执行精确计算的更多相关文章
- Java中Double类型的精确计算
import java.math.BigDecimal; public class DoubleUtil { private static final int DEF_DIV_SCALE = 5; / ...
- [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- java使用何种类型表示精确的小数?
问题 java使用何种类型表示精确的小数? 结论 float和double类型的主要设计目标是为了科学计算和工程计算,速度快,存在精度丢失 BigDecimal用来表示任意精确浮点数运算的类,在商业应 ...
- java的double类型如何精确到一位小数?
java的double类型如何精确到一位小数? //分钟转小时vacationNum = (double)Math.round(vacationNum/60*10)/10.0;overTimeNum ...
- 【44】java大数值剖析
基本的整数和浮点型精度不能满足需求,那么可以使用java.math中的两个类:BigInteger和BigDecimal. BigInteger和BigDecimal介绍: 这两个类可以处理包含任意长 ...
- JAVA 各种数值类型最大值和最小值 Int, short, char, long, float,&nbs
转载地址:http://blog.sina.com.cn/s/blog_5eab3d430101fdv6.html 代码片段: fmax = Float.MAX_VALUE; fmin = Float ...
- Java工具类之浮点精确计算
public class Arith { // 默认除法运算精度 private static final int DEF_DIV_SCALE = 10; // 构造器私有,让这个类不能实例化 pri ...
- Java 数值类型以及计算
前段时候写了一个对外提供的接口,其中有一个数值校验的计算.在测试的过程中发现5.6-1.6 != 4,在反复的测试过程中发现double类型的数值为有精度丢失的现象,看来还是基础知识不牢固,所以就在网 ...
- 关于java中Double类型的运算精度问题
标题 在Java中实现浮点数的精确计算 AYellow(原作) 修改 关键字 Java 浮点数 精确计算 问题的提出:如果我们编译运行下面这个程序会看到什么?publi ...
随机推荐
- tp5框架中jquery+ajax分页
jaxa分页,点击按钮直接替换数据, //php代码$page=Request::instance()->param("page"); $page = empty($page ...
- [原]vue中各模块的实际引用
检查发现: 1.vue实际引用文件配置位置 alias: { 'vue$': 'vue/dist/vue.esm.js', 此位置替换了vue包内的package.json中定义的位置 } 2.vue ...
- xml实现登录表单验证
定义: XML(eXtended Markup Language,可扩展标记语言)提供了一套跨平台.跨网络.跨程序的语言的数据描述方式,使用XML可以方便地实现数据交换.系统配置.内容管理等常见功能. ...
- BP神经网络与Python实现
人工神经网络是一种经典的机器学习模型,随着深度学习的发展神经网络模型日益完善. 联想大家熟悉的回归问题, 神经网络模型实际上是根据训练样本创造出一个多维输入多维输出的函数, 并使用该函数进行预测, 网 ...
- python出现编码问题的原因及编码问题的解决
1,为什么出现编码问题? 一般出现编码问题主要有四个方面: 一,解释器默认的编码和自己文件头编码是否一致 二,操作系统的语言设置问题 三,Terminal使用的编码问题 所有出现乱码的原因都可以归结为 ...
- SVD及其在推荐系统中的作用
本文先从几何意义上对奇异值分解SVD进行简单介绍,然后分析了特征值分解与奇异值分解的区别与联系,最后用python实现将SVD应用于推荐系统. 1.SVD详解 SVD(singular value d ...
- django 表单使用
Django提供对表单处理的支持,可以简化并自动化大部分的表单处理工作. 1 定义表单类 表单系统的核心部分是Django 的Form类. Django 的数据库模型描述一个对象的逻辑结构.行为以及展 ...
- CSS文本超出指定行数省略显示
单行: overflow: hidden; text-overflow: ellipsis; white-space: nowrap; 2行: font-size: 17px;overflow: hi ...
- git-如何不写注释能自动带上修改文件信息
背景:每次提交git,都要写注释,有些情况注释不太好写,或者根本没有必要写,这时可以通过自动加注释方法,比如可以追加修改了哪些文件 解决:通过shell脚本,在脚本里面写git命令,add commi ...
- python脚本批量复制文件
1.拷贝一个目录下的所有文件及文件夹到另一个目录下(递归拷贝) # cat /home/test.py #!/usr/bin/python import os import shutil def ...