一:相除精度丢失的问题

  BigDecimal的api除法相对加减乘要实现的复杂多了,只介绍常用的我遇到的问题:

  问题:两数相除,如果9/3=3整除没问题,但是10/3=0.33333333......除不尽,这里不能让电脑一直除不尽,所以BigDecimal做出一些限制;

   必须按照(数,保留小数位(最好要合理限制最大精度),舍入方式)来操作

 

   否则就会抛出异常,例如:

 public static void main(String[] args) {

        BigDecimal a = new BigDecimal(10);
BigDecimal b = new BigDecimal(3);
BigDecimal c = a.divide(b);
}

   执行:抛出

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1616)

二:舍入方式精度丢失的问题

  多数相乘时,请勿先进行四舍五入或者其他的方式,以最终计算结果为基础进行取舍精度,虽然一说就明白,但是这一个编码的习惯问题,特别是在金融行业。

  舍入方式需要弄明白自己的业务才用,别为了用而随便选一个用

  1.ROUND_UP:四舍五入模式从零四舍五入。

public static void main(String[] args) {

        BigDecimal a = new BigDecimal(0.31);
BigDecimal b = new BigDecimal(3);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_UP);
LOGGER.error("原值:0.1033333...///"+c.toString()+"=0.2"); //结论:0-9都是向前进一位(且当0后还有小数位为前提)
}

  2.ROUND_DOWN 四舍五入模式到四舍五入接近零。

public static void main(String[] args) {
     
BigDecimal a = new BigDecimal(0.39);
BigDecimal b = new BigDecimal(1);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_DOWN);
LOGGER.error("原值:0.39///"+c.toString()+"=0.3");
      //结论:1-9都是向前进一位
}

  3.ROUND_CEILING 四舍五入到正无穷。

public static void main(String[] args) {

        BigDecimal a = new BigDecimal(0.301);
BigDecimal b = new BigDecimal(1);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_CEILING);
LOGGER.error("原值:0.301///"+c.toString()+"=0.4");
    //结论:与第一种类似,区别就是舍入到正无穷的范围大,当值为负数时舍入失效,当用第四种解决
}

  4.ROUND_FLOOR 四舍五入到负无穷

public static void main(String[] args) {

        BigDecimal a = new BigDecimal(-0.301);
BigDecimal b = new BigDecimal(1);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_FLOOR);
LOGGER.error("原值:0.301///"+c.toString()+"=0.4");
     //结论:与上面的正无穷舍入的方式相反,可以互补
}

  5.ROUND_HALF_UP 四舍五入方式四舍五入,除非两个邻边距离相等,则四舍五入。

public static void main(String[] args) {

        BigDecimal a = new BigDecimal(-0.36);
BigDecimal b = new BigDecimal(1);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_UP);
LOGGER.error("原值:-0.36///"+c.toString()+"=-0.4");
//结论:正负数相同,以5为分界,<=5舍掉,>5的进1
}

  6.ROUND_HALF_DOWN 四舍五入模式四舍五入,除非两个邻边距离相等

public static void main(String[] args) {
BigDecimal a = new BigDecimal(-0.35);
BigDecimal b = new BigDecimal(1);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_DOWN );
LOGGER.error("原值:-0.35///"+c.toString()+"=-0.3");
//结论:正负数相同,以5为分界,<=5舍掉,>5的进1
}

  7.ROUND_HALF_EVEN 四舍五入的方式是四舍五入,除非两个邻边是等距的,在这种情况下,四舍五入对甚至邻居。

public static void main(String[] args) {
BigDecimal a = new BigDecimal(-0.35);
BigDecimal b = new BigDecimal(1);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_EVEN );
LOGGER.error("原值:-0.35///"+c.toString()+"=-0.3");
//结论:正负数相同,以5为分界,<=5舍掉,>5的进1
}

  8.ROUND_UNNECESSARY 舍入模式,以断言所请求的操作具有精确值结果,因此不需要舍入。

public static void main(String[] args) {
BigDecimal a = new BigDecimal(-0.36);
BigDecimal b = new BigDecimal(1);
BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_EVEN );
LOGGER.error("原值:-0.36///"+c.toString()+"=-0.4");
//结论:正负数相同,以5为分界,<=5舍掉,>5的进1
// 断言中使用的,实际开发过程中最好不用
}

三:BigDecimal取值范围的 validation 校验问题总结

  常常在与客户端交互时需要做很多校验,在javax.validation下面有很多不错的校验规则

  

  @NotNull :不为空,适用任何地方(@NotBlank只是用字符类型)

  @DecimalMax:取得最大值范围

   @DecimalMin(value = "0.00", message = "") 取值最小值

三:BigDecimal精度科学计数法问题总结

  BigDecimal有一种方法是:stripTrailingZeros(),它提供了去掉小数点后面的多余的0,但是问题是:

  

    public static void main(String[] args) {
BigDecimal A = BigDecimal.valueOf(0.36000).stripTrailingZeros();
BigDecimal B = new BigDecimal(0.36000).stripTrailingZeros();
BigDecimal zeroDecimal = new BigDecimal(0.000).stripTrailingZeros();
System.out.println("原值0.36000//////"+A.toPlainString()+"===0.36");
System.out.println("原值0.36000//////"+B.toPlainString()+"===35999999999999998667732370449812151491641998291015625");
System.out.println("原值0.00000//////"+zeroDecimal+"==0.0000////"+zeroDecimal.toPlainString()+"==0");
}

  ①:导出是excel会以科学计数法展示数据,如120 -》1.2+E2;

  ②:如果0.000然后用stripTrailingZeros()是无效的,导出时toPlainString()加上之后就可以了;

  ③:慎用new BigDecimal();源代码如下;

/**这个构造函数的结果可能有些不可预测。
*可能会假设编写{@code new BigDecimal(0.1)}
* Java创建一个完全等于的{@code BigDecimal}
* 0.1(未缩放值为1,刻度为1),但它是
*实际上等于 *0.1000000000000000055511151231257827021181583404541015*625.
**/ public BigDecimal(double val) {
this(val,MathContext.UNLIMITED);
}

BigDecimal常被忽略的问题的更多相关文章

  1. JavaScript之parseInt()数值转换常被忽略的问题

    使用parseInt()你可以从字符串中获取数值,该方法接受另一个基数参数,这经常省略,但不应该.当字符串以”0″开头的时候就有可能会出问题,例如,部分时间进入表单域,在ECMAScript 3中,开 ...

  2. [转]关于event的两个常被忽略的api:isDefaultPrevented()和preventDefault()

    今天在robert penner(as3 singal的作者)的一篇blog文中顺藤摸瓜到了darron schall的另外一篇blog文(Creating Default, Cancelable E ...

  3. 小议常被忽略的a标签:visited属性的特殊用法

    CSS1/CSS2对于a定义了4个伪类, :link  a标签未访问时的样式 :active  a标签mousedown时的样式 :hover  a标签mouseover时的样式 :visited  ...

  4. 【javascript常见面试题】常见前端面试题及答案

    转自:http://www.cnblogs.com/syfwhu/p/4434132.html 前言 本文是在GitHub上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典.很有代表性.上 ...

  5. 说说DOM的那些事儿

    引子 先来一颗栗子: <img src="/sub/123.jpg" alt="test" /> <script type="tex ...

  6. 前端小知识点---html换行被解析为空格的相关知识

    这个系列主要记录一下常被忽略但又经常产生影响的知识点,纯做个记录,方便查询 html换行被解析为空格也是常说的3像素空隙的问题,根据测试不同浏览器产生的空隙大小会不一样,Chrome,Firefox, ...

  7. Top 15 不起眼却有大作用的 .NET功能集

    目录 1. ObsoleteAttribute2. 设置默认值属性: DefaultValueAttribute3. DebuggerBrowsableAttribute4. ??运算符5. Curr ...

  8. 第2章 两种调用JS的方法——在HTML中使用JavaScript

    一. <script>标记 第一种方法是把 <sript></script>直接放到head和script两个标记之间(title下面,</head>上 ...

  9. js中的preventDefault与stopPropagation详解

    本篇文章主要是对js中的preventDefault与stopPropagation进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 首先讲解一下js中preventDefault和stopP ...

随机推荐

  1. 使用Ansible实现数据中心自动化运维管理

    长久以来,IT 运维在企业内部一直是个耗人耗力的事情.随着虚拟化的大量应用.私有云.容器的不断普及,数据中心内部的压力愈发增加.传统的自动化工具,往往是面向于数据中心特定的一类对象,例如操作系统.虚拟 ...

  2. .NET手记-ASP.NET MVC快速分页的实现

    对于Web应用,展示List是很常见的需求,随之而来的常见的分页组件.jQuery有现成的分页组件,网上也有着大量的第三方分页组件,都能够快速实现分页功能.但是今天我描述的是用基本的C#和html代码 ...

  3. css选择符权重

    css选择符权重 目录 css选择符权重 css选择器权重列表 CSS选择符冲突处理 css选择符权重 css选择器权重列表 选择器 权重 内联样式 1000 ID 0100 CLASS 0010 属 ...

  4. 十大经典排序算法+sort排序

    本文转自:十大经典排序算法,其中有动图+代码详解,本文简单介绍+个人理解. 排序算法 经典的算法问题,也是面试过程中经常被问到的问题.排序算法简单分类如下: 这些排序算法的时间复杂度等参数如下: 其中 ...

  5. Xamarin.Android 压缩图片并上传到WebServices

    随着手机的拍照像素越来越高,导致图片赞的容量越来越大,如果上传多张图片不进行压缩.质量处理很容易出现OOM内存泄漏问题. 最近做了一个项目,向webservices上传多张照片,但是项目部署出来就会出 ...

  6. 我是如何利用Github Pages搭建起我的博客,细数一路的坑

    1.前言 其实早在这之前我就一直想过写博客,但由于种种原因一直没有去学习这方面的知识,最近半个月(从开始动手到搭建好)一直陆陆续续的在着手这方面的工作.从开始到搭建完成的过程中遇到了很多困难,因为在这 ...

  7. 以ActiveMQ为例JAVA消息中间件学习【3】——SpringBoot中使用ActiveMQ

    前言 首先我们在java环境中使用了ActiveMQ,然后我们又在Spring中使用了ActiveMQ 本来这样已经可以了,但是最近SpringBoot也来了.所以在其中也需要使用试试. 可以提前透露 ...

  8. Java中锁分类

    锁的分类大致如下:公平锁/非公平锁可重入锁/不可重入锁独享锁/共享锁乐观锁/悲观锁分段锁 1.公平锁/非公平锁公平锁就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的:而非公平锁是允许插队的 ...

  9. CynosDB技术详解——存储集群管理

    本文由腾讯云数据库发表 前言 CynosDB是架构在CynosFS之上的分布式关系数据库系统,为最大化利用存储资源,平衡资源之间的竞争,检查资源使用情况,需要一套高效稳定的分布式集群管理系统(SCM: ...

  10. python的Web框架,html分页

    使用简单的算法得出页码数,然后在html中获取即可.仅供参考. views的写法 def crm_stu(request): section = '教师后台管理页' search = request. ...