java 加减乘除工具类_BigDecimal - 用于加、减、乘、除计算的工具类

本文探讨了在开发中如何选择合适的数据类型进行计算,重点关注了Java中的BigDecimal类及其在处理高精度运算时的使用场景、MathContext和RoundingMode的重要性。通过实例展示了如何避免精度损失并正确使用BigDecimal进行加、减、乘、除运算,以及注意事项。
部署运行你感兴趣的模型镜像

开发过程中经常会需要进行一些数据的运算操作,比如加、减、乘、除,但是在计算过程中,到底使用哪种数据类型进行计算才是最合适的呢?

1、数据类型

1.1、 基础数据类型

int:只能进行整数的计算,应用范围单一。

float:单精度浮点型,可以进行小数类型的计算,但是容易丢失精度。

double:双精度浮点型,精确度比float高,消耗的内存也比float高,但是也容易丢失精度。

String:字符串类型,没法进行运算操作,但是恰恰要用到它和另外一种对象来进行数据的运算操作。

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

1.2、BigDecimal 详细介绍

以下是关于BigDecimal 的官方文档介绍,以及自己的一些总结。涉及到BigDecimal 以及和它相关联的MathContext、RoundingMode这两个类。

java.math.BigDecimal

javase官方文档的描述:

不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。因此,BigDecimal 表示的数值是 (unscaledValue × 10-scale)。

BigDecimal 类提供以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。toString() 方法提供 BigDecimal 的规范表示形式。

BigDecimal 类使用户能完全控制舍入行为。如果未指定舍入模式,并且无法表示准确结果,则抛出一个异常;否则,通过向该操作提供适当的 MathContext 对象,可以对已选择的精度和舍入模式执行计算。在任何情况下,可以为舍入控制提供八种舍入模式。使用此类(例如,ROUND_HALF_UP)中的整数字段来表示舍入模式已过时;应改为使用 RoundingMode enum(例如,RoundingMode.HALF_UP)的枚举值。

java.math.MathContext

javase官方文档描述

该对象是封装上下文设置的不可变对象,它描述数字运算符的某些规则,例如由 BigDecimal 类实现的规则。

基本独立设置为:

1、precision:某个操作使用的数字个数;结果舍入到此精度

2、roundingMode:一个 RoundingMode 对象,该对象指定舍入使用的算法。

java.math.RoundingMode

javase官方文档描述

为可能丢弃精度的数值操作指定一种舍入行为。每种舍入模式都指示如何计算返回舍入结果位数的最低有效位。如果返回的位数比表示精确数值结果所需的位数少,则舍弃的位数称为舍弃部分,而不管这些位数对数值的作用如何。换句话说,假设是一个数值,舍弃部分的绝对值可能大于 1。

这是一种枚举类型,以下是它的8种舍入方式的总结:

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。

来个表格看一下吧(这是javase官方api的图表)根据给定的舍入模式将输入数字舍入为一位数的结果:

输入数字

UP

DOWN

CEILING

FLOOR

HALF_UP

HALF_DOWN

HALF_EVEN

UNNECESSARY

5.5

6

5

6

5

6

5

6

抛出 ArithmeticException

2.5

3

2

3

2

3

2

2

抛出 ArithmeticException

1.6

2

1

2

1

2

2

2

抛出 ArithmeticException

1.1

2

1

2

1

1

1

1

抛出 ArithmeticException

1.0

1

1

1

1

1

1

1

1

-1.0

-1

-1

-1

-1

-1

-1

-1

-1

-1.1

-2

-1

-1

-2

-1

-1

-1

抛出 ArithmeticException

-1.6

-2

-1

-1

-2

-2

-2

-2

抛出 ArithmeticException

-2.5

-3

-2

-2

-3

-3

-2

-2

抛出 ArithmeticException

-5.5

-6

-5

-5

-6

-6

-5

-6

抛出 ArithmeticException

注意:以上8中枚举类型,在使用中需要特别注意,尤其是除法运算中的时候,需要制定枚举类型,切记,切记。

2、使用环境

在进行开发工作中,有时候会需要对一些数据进行加、减、乘、除的运算操作,这时候无论用int、float还是double进行计算,都会存在精度丢失的风险,这时候我们需要借助一个对象BigDecimal 来帮助我们进行计算。

BigDecimal 的构造方法有许多个,构造参数可以传int、float、double、String,但是经实际应用,使用构造参数为float或double类型的构造参数进行计算的时候,转换的BigDecimal 对象都会导致精度的丢失。通过实际验证,使用构造参数为String的构造方法可以避免精度丢失。

注意: 在以后需要进行加、减、乘、出计算的参数,都尽量用String来接收服务器返回的参数。

3、使用方式

以下是封装的用于进行计算的方法:

加法

/**

* 提供精确加法计算的add方法(例:1+2,1是被加数,2是加数)

*

* @param value1 被加数

* @param value2 加数

* @return 两个参数的和

*/

public static String add(String value1, String value2) {

BigDecimal b1 = new BigDecimal(value1);

BigDecimal b2 = new BigDecimal(value2);

return b1.add(b2).toString();

}

减法

/**

* 提供精确减法运算的sub方法(例:1-2,1是被减数,2是减数)

*

* @param value1 被减数

* @param value2 减数

* @return 两个参数的差

*/

public static String sub(String value1, String value2) {

BigDecimal b1 = new BigDecimal(value1);

BigDecimal b2 = new BigDecimal(value2);

return b1.subtract(b2).toString();

}

乘法

/**

* 提供精确乘法运算的mul方法(例:1*2,1是被乘数,2是乘数)

*

* @param value1 被乘数

* @param value2 乘数

* @return 两个参数的积

*/

public static String mul(String value1, String value2) {

BigDecimal b1 = new BigDecimal(value1);

BigDecimal b2 = new BigDecimal(value2);

return b1.multiply(b2).toString();

}

除法

/**

* 提供精确的除法运算方法div(例:1÷2,1是被除数,2是除数)

*

* @param value1 被除数

* @param value2 除数

* @param scale 精确范围

* @return 两个参数的商

* @throws IllegalAccessException

*/

public static String div(String value1, String value2, int scale) throws IllegalAccessException {

//如果精确范围小于0,抛出异常信息

if (scale < 0) {

throw new IllegalAccessException("精确度不能小于0");

}

BigDecimal b1 = new BigDecimal(value1);

BigDecimal b2 = new BigDecimal(value2);

//指定枚举类型,可以指定RoundingMode的8种枚举类型之一,对这8种枚举类型如果有疑问,可以参考上面RoundingMode的总结和描述。

//这里指定的DOWN,对应RoundingMode的ROUND_DOWN模式,会直接舍去精确度后面的数值。

return b1.divide(b2, scale, RoundingMode.DOWN).toString();

}

4、使用总结

用以上四个方法就可以应付开发过程中最基础的加、减、乘、除的运算了,但是在使用中要注意的情况:被减数和减数、被除数和除数的位置不要颠倒了,否则就会和预期的计算结果相差十万八千里了。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

唔,其实里面就是一个工具类加减乘除、保留两位小数。一共5个方法。。。emmmm.....为啥分这么高呢。因为宝宝想分想疯了。 附代码,有土豪就打赏打赏,没土豪的直接拿去使吧。 package cn.cisdom.base.utils; import java.math.BigDecimal; import java.text.DecimalFormat; public class Calculation { public static final DecimalFormat df = new DecimalFormat("######0.00"); /** * @methodName format2point * @desc 保留两位小数点 * @param value * @return java.lang.String * @author xm * @create 2018/6/7 12:03 **/ public static String format2point(Number value) { return df.format(value); } public static Double add(Number value1, Number value2) { BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.add(b2).doubleValue(); } /** * 提供精确的运算。 * * @param value1 * 数 * @param value2 * 被数 * @return 两个参数的差 */ public static Double sub(Number value1, Number value2) { BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.subtract(b2).doubleValue(); } /** * 提供精确的运算。 * * @param value1 * 被数 * @param value2 * 数 * @return 两个参数的积 */ public static Double mul(Number value1, Number value2) { BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.multiply(b2).doubleValue(); } /** * 提供精确的运算。 * * @param value1 * 数 * @param value2 * 被数 * @return 数/被数 */ public static Double div(Number value1, Number value2) { //MathContext mc = new MathContext(2, RoundingMode.HALF_DOWN);//精度为2,舍入模式为大于0.5进1,否则舍弃 BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.divide(b2).doubleValue(); } public static void main(String[] args) { Double aDouble=Calculation.add(56.9, 1.67); System.out.println(aDouble); Double bDouble=Calculation.sub(99.2,aDouble); System.out.println(bDouble); } }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值