BigDecimal BigInteger的使用
创始人
2024-05-16 07:13:38
0

1、BigDiCemal

【问题】在项目中,我们进行计算的时候,有时候需要考虑 四舍五入,精度丢失的问题,面对这种问题,我们应该怎么处理?

 System.out.println(0.2+0.1);System.out.println(0.3-0.1);System.out.println(0.4*0.1);System.out.println(0.2+1);

输出结果: 

请忽略 浮点型 与整数的计算。

我们看到上面三个测试 浮点型与浮点型四则运算,运算结果并不是准确的,也不是我们所想要的。

造成这种现象的原因:

因为不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。

注:根本原因是:十进制值通常没有完全相同的二进制表示形式;十进制数的二进制表示形式可能不精确。只能无限接近于那个值。

另外注意一点,整数与浮点数计算,或 整数向浮点数转换的时候,会向下转型。

【怎么解决】

1、简介

java提供了 BigDecimal这个api,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

2、构造器:

BigDecimal(int)       创建一个具有参数所指定整数值的对象。 

BigDecimal(double) 创建一个具有参数所指定双精度值的对象。 //不推荐使用

BigDecimal(long)    创建一个具有参数所指定长整数值的对象。 

BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。 推荐使用

这里注意一个问题,对于double 类型的数据,最好不要直接传入BigDecimal构造函数,创建 BigDecimal对象,会出现精度问题,计算错误,建议将double转换成String

比如:

 

3、方法描述

add(BigDecimal)        BigDecimal对象中的值相加,然后返回这个对象。 

subtract(BigDecimal) BigDecimal对象中的值相减,然后返回这个对象。 

multiply(BigDecimal)  BigDecimal对象中的值相乘,然后返回这个对象。 

divide(BigDecimal)     BigDecimal对象中的值相除,然后返回这个对象。 

toString()                将BigDecimal对象的数值转换成字符串。 

doubleValue()          将BigDecimal对象中的值以双精度数返回。 

floatValue()             将BigDecimal对象中的值以单精度数返回。 

longValue()             将BigDecimal对象中的值以长整数返回。 

intValue()               将BigDecimal对象中的值以整数返回

在实战中,比较实用的几个方法

stripTrailingZeros():去除尾部所有的0,并返回一个BigDecimal类型的数据,不能保证不是科学计数法。
后加toString()把BigDecimal类型的数据转化成String类型数据,但还是不能保证不是科学计数法。
后加toPlainString()把BigDecimal类型的数据转化成String类型数据,并保证不是科学计数法。

比如上边的例子中,我想去掉最后 1.2000的零

 

除了上述的四则运算,和值输出以外,BigDecimal 更常用的是 取一个数的某一部分,可以是取整数,也可以规定保留的精度

setScale(保留小数点后几位,舍入方法) 

1、UP(BigDecimal.ROUND_UP):远离零方向舍入。向远离0的方向舍入,也就是说,向绝对值最大的方向舍入,只要舍弃位非0即进位。


2、DOWN(BigDecimal.ROUND_DOWN):趋向0方向舍入。向0方向靠拢,也就是说,向绝对值最小的方向输入,注意:所有的位都舍弃,不存在进位情况。


3、CEILING(BigDecimal.ROUND_CEILING):向正无穷方向舍入。向正最大方向靠拢,如果是正数,舍入行为类似于ROUND_UP;如果为负数,则舍入行为类似于ROUND_DOWN.注意:Math.round方法使用的即为此模式。


4、FLOOR(BigDecimal.ROUND_FLOOR):向负无穷方向舍入。向负无穷方向靠拢,如果是正数,则舍入行为类似ROUND_DOWN,如果是负数,舍入行为类似以ROUND_UP。


5、HALF_UP(BigDecimal.ROUND_HALF_UP):最近数字舍入(5舍),这就是我们经典的四舍五入。


6、HALF_DOWN(BigDecimal.ROUND_HALF_DOWN):最近数字舍入(5舍)。在四舍五入中,5是进位的,在HALF_DOWN中却是舍弃不进位。

5.5 -> 5
2.5 -> 2
1.6 -> 2
1.1 -> 1
1.0 -> 1
-1.0 -> -1
-1.1 -> -1
-1.6 -> -2
-2.5 -> -2
-5.5 -> -5

7、HALF_EVEN(BigDecimal.ROUND_HALF_EVEN):银行家算法。四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。

5.5 -> 6
2.5 -> 2
1.6 -> 2
1.1 -> 1
1.0 -> 1
-1.0 -> -1
-1.1 -> -1
-1.6 -> -2
-2.5 -> -2
-5.5 -> -6

8、UNNECESSARY(BigDecimal.ROUND_UNNECESSARY):断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

精确到一位小数点
1.0—>1
1.1抛异常

参考链接:https://blog.csdn.net/xnkjdx105/article/details/124213231

   

 

所以,我们在面对一般、甚至精确要求非常高的情况下,对小数位进行操作的时候,都可以考虑 BigDecimal

特别是求一个浮点数,保留其后xx位小数的时候,最为可靠。

1)把浮点数转为String   //防止精度丢失

2)调用new BigDecimal(String d),将浮点型转换成更为精确的BigDecimal对象

3) 使用BigDecimal的setScale 方法,求得所需要的精确的结果

对于整形运算,我们为了防止它的结果向下转型,也可以考虑使用Bigdecimal  比如:

 我们日常随意的书写,会造成各种类型转换的隐患,

 输出结果:

2、BigInt

//TODO

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...