java后端实现加减乘除和比例计算

在 java.math 包中提供了 API 类 BigDecimal 用来对超过 16位有效位的数进行精确的运算。
BigDecimal 所创建的是对象,所以不能使用 +、-、*、/、等算术运算符直接对其对象进行数学运算。

首先需要了解 BigDecimal 一共有4种构造方法:

 //创建一个具有参数所指定整数值的对象BigDecimal(int)//创建一个具有参数所指定双精度值的对象BigDecimal(double)//创建一个具有参数所指定整数值的对象BigDecimal(long)//创建一个具有参数所指定以字符串表示的数值的对象BigDecimal(String)//这里对比了两种形式,第一种直接value写数字的值,第二种用string来表示BigDecimal num1 = new BigDecimal(0.005);BigDecimal num2 = new BigDecimal(1000000);BigDecimal num3 = new BigDecimal(-1000000);    //尽量用字符串的形式初始化BigDecimal num12 = new BigDecimal("0.005");BigDecimal num22 = new BigDecimal("1000000");BigDecimal num32 = new BigDecimal("-1000000");

1、加减乘除

 //加法 add()BigDecimal result1 = num1.add(num2);BigDecimal result12 = num12.add(num22);//减法 subtract()BigDecimal result2 = num1.subtract(num2);BigDecimal result22 = num12.subtract(num22);//乘法 multiply()BigDecimal result3 = num1.multiply(num2);BigDecimal result32 = num12.multiply(num22);//绝对值 abs()BigDecimal result4 = num3.abs();BigDecimal result42 = num32.abs();//除法 divide()//num1、num12 除数, 20 精确小数位,  BigDecimal.ROUND_HALF_UP 舍入模式BigDecimal result5 = num2.divide(num1,20,BigDecimal.ROUND_HALF_UP);BigDecimal result52 = num22.divide(num12,20,BigDecimal.ROUND_HALF_UP);//去除末尾多余的0:new BigDecimal("100.000").stripTrailingZeros().toPlainString();

这里把result全部输出可以看到结果
这里出现了差异,这也是为什么初始化建议使用string的原因

※ 注意:

1)System.out.println()中的数字默认是double类型的,double类型小数计算不精准。

2)使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的!

因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。这一点在BigDecimal类的构造方法注释中有说明。

除法divide()参数使用

使用除法函数在divide的时候要设置各种参数,要精确的小数位数和舍入模式,不然会出现报错
我们可以看到divide函数配置的参数如下

 //即为(BigDecimal divisor 除数, int scale 精确小数位,  int roundingMode 舍入模式)Public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

但是舍入模式有很多种 BigDecimal.ROUND_XXXX_XXX, 具体都是什么意思呢

八种舍入模式解释如下

1)ROUND_UP

舍入远离零的舍入模式。

在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。

注意,此舍入模式始终不会减少计算值的大小。

2)ROUND_DOWN

接近零的舍入模式。

在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1,即截短)。

注意,此舍入模式始终不会增加计算值的大小。

3)ROUND_CEILING

接近正无穷大的舍入模式。

如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;

如果为负,则舍入行为与 ROUND_DOWN 相同。

注意,此舍入模式始终不会减少计算值。

4)ROUND_FLOOR

接近负无穷大的舍入模式。

如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;

加粗样式如果为负,则舍入行为与 ROUND_UP 相同。

注意,此舍入模式始终不会增加计算值。

5)ROUND_HALF_UP

向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。

如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。

注意,这是我们大多数人在小学时就学过的舍入模式(四舍五入)。

6)ROUND_HALF_DOWN

向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。

如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同(五舍六入)。

7)ROUND_HALF_EVEN

向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。

如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;

如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。

注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。

此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。

如果前一位为奇数,则入位,否则舍去。

以下例子为保留小数点1位,那么这种舍入方式下的结果。

1.15>1.2 1.25>1.2

8)ROUND_UNNECESSARY

断言请求的操作具有精确的结果,因此不需要舍入。

如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

举个例子:计算1÷3的结果(最后一种ROUND_UNNECESSARY在结果为无限小数的情况下会报错)

2、比较大小

//前提为a、b均不能为nullBigDecimal a = new BigDecimal("xx");BigDecimal b = new BigDecimal("xx");if(a.compareTo(b) == -1){System.out.println("a小于b");}if(a.compareTo(b) == 0){System.out.println("a等于b");}if(a.compareTo(b) == 1){System.out.println("a大于b");}if(a.compareTo(b) > -1){System.out.println("a大于等于b");}if(a.compareTo(b) < 1){System.out.println("a小于等于b");}

3、BigDecimal总结

在需要精确的小数计算时再使用BigDecimal,BigDecimal的性能比double和float差,在处理庞大,复杂的运算时尤为明显。故一般精度的计算没必要使用BigDecimal。尽量使用参数类型为String的构造函数。

BigDecimal都是不可变的(immutable)的, 在进行每一次四则运算时,都会产生一个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。

工具类推荐

package com.vivo.ars.util;
import java.math.BigDecimal;/*** 用于高精确处理常用的数学运算*/
public class ArithmeticUtils {//默认除法运算精度private static final int DEF_DIV_SCALE = 10;/*** 提供精确的加法运算** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static double add(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.add(b2).doubleValue();}/*** 提供精确的加法运算** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static BigDecimal add(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.add(b2);}/*** 提供精确的加法运算** @param v1    被加数* @param v2    加数* @param scale 保留scale 位小数* @return 两个参数的和*/public static String add(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的减法运算** @param v1 被减数* @param v2 减数* @return 两个参数的差*/public static double sub(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.subtract(b2).doubleValue();}/*** 提供精确的减法运算。** @param v1 被减数* @param v2 减数* @return 两个参数的差*/public static BigDecimal sub(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.subtract(b2);}/*** 提供精确的减法运算** @param v1    被减数* @param v2    减数* @param scale 保留scale 位小数* @return 两个参数的差*/public static String sub(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @return 两个参数的积*/public static double mul(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.multiply(b2).doubleValue();}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @return 两个参数的积*/public static BigDecimal mul(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.multiply(b2);}/*** 提供精确的乘法运算** @param v1    被乘数* @param v2    乘数* @param scale 保留scale 位小数* @return 两个参数的积*/public static double mul(double v1, double v2, int scale) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return round(b1.multiply(b2).doubleValue(), scale);}/*** 提供精确的乘法运算** @param v1    被乘数* @param v2    乘数* @param scale 保留scale 位小数* @return 两个参数的积*/public static String mul(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到* 小数点以后10位,以后的数字四舍五入** @param v1 被除数* @param v2 除数* @return 两个参数的商*/public static double div(double v1, double v2) {return div(v1, v2, DEF_DIV_SCALE);}/*** 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指* 定精度,以后的数字四舍五入** @param v1    被除数* @param v2    除数* @param scale 表示表示需要精确到小数点以后几位。* @return 两个参数的商*/public static double div(double v1, double v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指* 定精度,以后的数字四舍五入** @param v1    被除数* @param v2    除数* @param scale 表示需要精确到小数点以后几位* @return 两个参数的商*/public static String div(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v1);return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的小数位四舍五入处理** @param v     需要四舍五入的数字* @param scale 小数点后保留几位* @return 四舍五入后的结果*/public static double round(double v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b = new BigDecimal(Double.toString(v));return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供精确的小数位四舍五入处理** @param v     需要四舍五入的数字* @param scale 小数点后保留几位* @return 四舍五入后的结果*/public static String round(String v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b = new BigDecimal(v);return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 取余数** @param v1    被除数* @param v2    除数* @param scale 小数点后保留几位* @return 余数*/public static String remainder(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 取余数  BigDecimal** @param v1    被除数* @param v2    除数* @param scale 小数点后保留几位* @return 余数*/public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);}/*** 比较大小** @param v1 被比较数* @param v2 比较数* @return 如果v1 大于v2 则 返回true 否则false*/public static boolean compare(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);int bj = b1.compareTo(b2);boolean res;if (bj > 0)res = true;elseres = false;return res;}
}

好事定律:每件事最后都会是好事,如果不是好事,说明还没到最后。

java后端实现加减乘除和比例计算相关推荐

  1. Java后端进行经纬度点抽稀聚合,HTML呈现及前端聚合实现点聚合~

    Java后端进行经纬度点抽稀聚合,HTML呈现及前端聚合实现点聚合~ 1. 效果图~ 1.1 前端实现聚合及呈现 1.2 后端实现点聚合,前端渲染呈现效果图 2. 原理 3. 源码 3.1 前端JS实 ...

  2. 深入分析Spark任务调度的原理--Java后端同学入门Spark编程系列

    作者:陌北有棵树,Java人,架构师社区合伙人! 之前写了一篇:<我作为Java后端,分享一下入门Spark编程的经历!> 上篇是Spark入门的第一篇,写了一些关于Spark编程中RDD ...

  3. 我作为Java后端,分享一下入门Spark编程的经历!

    作者:陌北有棵树,玩Java,架构师社区合伙人! 最近由于工作任务,需要掌握大数据技术栈的相关知识,于是开始了入门大数据的漫漫之路. 相比传统Java后端的技术栈来说,大数据关注的技术点可以说是另一套 ...

  4. 安卓java模拟器_用大白话告诉你:Java 后端到底是在做什么?

    作者:黄小斜 阅读本文大概需要 6 分钟. 新手程序员通常会走入一个误区,就是认为学习了一门语言,就可以称为是某某语言工程师了.但事实上真的是这样吗?其实并非如此. 今天我们就来聊一聊,Java 开发 ...

  5. java后端开发(九):mybatis的威力加强版之mybatis-plus

    前言 后端一半的时间都是在和关系型数据库打交道,那么虽然我们用 mybatis 这个 ORM 框架,简化代码的开发.但是代码中涉及到太多的重复操作,比如对用户的增删改查和对设备的增删改查.我们毕竟是贪 ...

  6. Android端+java后端+servlet+MySQL的型男塑造平台【前后端源代码+论文+答辩ppt】

    活动地址:毕业季·进击的技术er 目录 前言 第一章 绪论 1.1 背景和意义 1.2 国内外研究现状 1.3 论文研究目标与内容 1.4.减肥瘦身相关概念与计算方式介绍 第二章 需求分析 2.1 平 ...

  7. Java后端程序员都做些什么?

    这个问题来自于QQ网友,一句两句说不清楚,索性写个文章. 我刚开始做Web开发的时候,根本没有前端,后端之说. 原因很简单,那个时候服务器端的代码就是一切:接受浏览器的请求,实现业务逻辑,访问数据库, ...

  8. 微信运动步数:小程序+Java后端,源码可下载

    微信运动步数:小程序+Java后端 更多资源:www.jeeweixin.com 功能说明: 1.获取和展示用户的微信运动步数,计算卡路里: 2.用户打开小程序即可实现步数打卡入库: 3.通过日历展示 ...

  9. 4000字干货长文!从校招和社招的角度说说如何准备大厂Java后端面试?

    我觉得每一个技术人的梦想大概就是能够找一份大厂的 offer,我觉得这很正常,这并不是我们的饭后谈资而是每个技术人的追求.像阿里.腾讯.美团.字节跳动.京东等等大厂的技术氛围还是要明显优于一些创业型公 ...

最新文章

  1. RubyOnRails小资料
  2. mysql写放大,canvas实现图片根据滑块放大缩小效果
  3. 全flash站制作剖析
  4. 对TypeScript进行研究
  5. 部署egg需要用到pm2吗_使用宝塔面板部署校园综合服务平台项目
  6. 以实时风控场景为例,阿里云实时计算如何来做异常检测?
  7. php实现一个简单的购物网站
  8. java fileinputstream 安全管理器校验失败_Spring Boot 如何做参数校验?
  9. linux驱动架构变化,Linux网卡驱动架构分析
  10. GMS 地下水数值模拟
  11. 龙芯电脑安装debian 10 buster
  12. webpack 报错处理 Error: Cannot find module '@webassemblyjs/wast-parser'
  13. cocos2dx 自定义事件
  14. 单片机计时器100000秒以内
  15. Pytorch中shuffle=True的作用
  16. 爱情如水,宽容是杯~
  17. iphone修改app名称_iPhone6 plus怎么修改图标名字?苹果6 plus设置修改图标名字教程...
  18. 喜报 | 冠骋信息获2022年苏州市工程技术研究中心认定
  19. 【OpenAirInterface知识-2】OAI端到端部署之核心网部署
  20. 【转】LTE基本架构

热门文章

  1. Python3.x web.py安装报错
  2. 编译 cp2k 7.1 简略记录
  3. 【职场心理】如何控制自己的情绪,调节压力?
  4. uart转RS422
  5. floyd算法最短路径
  6. Shell脚本编程案例集(持续更新)
  7. 技术分享| 应急指挥调度平台需要这些技术支撑
  8. srm供应商关系管理系统
  9. css方式让div居于屏幕正中间
  10. 【ARM CPU 之 Cortex-M7 介绍】