java中小数的处理:高精度运算用bigDecimal类,精度保留方法,即舍入方式的指定

时间:2022-08-23 11:25:19

一、 计算机的小数计算一定范围内精确,超过范围只能取近似值:

    计算机存储的浮点数受存储bit位数影响,只能保证一定范围内精准,超过bit范围的只能取近似值。
java中各类型的精度范围参见:http://blog.csdn.net/longshenlmj/article/details/47616481
编程时注意:
doulbe类型的数,不能用等号判定是否相等(或者是一定范围内可以)。因为两次同样的计算(除法)结果可能出现小数部分不同。甚至极端的时候,初始化两个小数时,都可能不相等(用数值和字符串分别初始化bigdecimal的小数就会不等)

java小数处理方法的经验总结:

(1)小数计算对精度无要求时,使用float节省时间。

(2)如果有精度要求,用BigDecimal类处理(初始化必须使用字符串,因为用数值初始化会得到近似值,不准确),然后设置保留位数和 舍入法(half_up四舍五入,half_even银行家,half_down向下取整)

(3)精度要求低时可转化为整数处理(集体统一扩大数量级):
乘以10的级数转化为整数处理,小数点右移几位,但整数值不要超过对应类型的取值范围。比如保留4位小数,可统一乘以10000,然后只保留整数计算结果,保留近位的话就多乘一位。
这种方式在RTB项目MDSP的算法核心模块中使用,几十万的投放量,用int或long就可以处理,更大范围的整数处理BigInteger。

这样的好处是:

a,计算快,除了除法,其他运算上整数计算(加减乘)节省时间;
b,除法中,小数部分可直接省略,或向上取整(小数大于0时则加1)也可以让小数点多移动一位来保留进位。

二、java专门的小数运算类:BigDecimal类型(比double和float小数运算更精准的小数计算)

    float和double只能用来做科学计算或者是工程计算,在广域数值范围上提供较为精确的快速近似计算;而在商业计算要求结果精确(比如,有的编程语言中提供了专门的货币类型来处理),所以Java使用java.math.BigDecimal专门处理小数精度
构造器描述:
    BigDecimal(int)       创建一个具有参数所指定整数值的对象。
BigDecimal(double) 创建一个具有参数所指定双精度值的对象。
BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。

使用原则:初始化小数必须用String来够造,BigDecimal(String),因为用double的小数是近似值,不是精确值。

BigDecimal成员方法
    add(BigDecimal)        对象自身与参数相加,然后返回这个对象。
subtract(BigDecimal) 对象自身与参数相减,然后返回这个对象。
multiply(BigDecimal) 对象自身与参数相乘,然后返回这个对象。
divide(BigDecimal) 对象自身与参数相除,然后返回这个对象。
toString() BigDecimal对象的数值转换成对应的字符串。
doubleValue() BigDecimal对返回double值。
floatValue() BigDecimal对返回float。
longValue() BigDecimal对返回long值。
intValue() BigDecimal对返回int值。

三、java小数保留精度的舍入方式

1,java 常用的四舍五入法实现:

Math类中的round方法不能设置保留几位小数,但可以乘100达到保留2位的目的:
Math.round(value*100)/100.0; 或者,直接用java.text.DecimalFormat指定保留几位小数,用哪几种舍入法:
DecimalFormat decFormat = new DecimalFormat("#.00");
decFormat.setRoundingMode(RoundingMode.HALF_UP);

2,java的8种舍入方式:

1、 ROUND_UP:向上取整(丢掉小数,整数加1) 远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。

2、ROUND_DOWN:向下取整(丢掉小数)。趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。

3、ROUND_CEILING:向正无穷方向走,始终不会减少计算值。如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;如果为负,则舍入行为与 ROUND_DOWN 相同。Math.round()方法就是使用的此模式。

4、ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。

5、 HALF_UP:四舍五入,最近数字舍入(5进)。

6、 HALF_DOWN:四舍六入,最近数字舍入(5舍)。

7、 HAIL_EVEN:银行家舍入法。四舍六入五偶舍。即舍弃位4舍6入,当为5时看前一位,奇进偶舍。向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
也就是说,如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同; 如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。 8、ROUND_UNNECESSARY 断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

四、BigDecimal的java代码实例

package test;

import java.math.BigDecimal;

public class bigDecimalTest {

    public static void main(String[] args) {
BigDecimal a = new BigDecimal(1);
BigDecimal b = new BigDecimal(3); BigDecimal sum = new BigDecimal("0");
for(int i=0;i<2;i++)
{
sum = sum.add(a);
}
//除法运算
System.out.println("a/b="+a.divide(b,5,BigDecimal.ROUND_HALF_UP).doubleValue());
System.out.println("a/b="+a.divide(b,6,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")));
System.out.println("a/b="+a.divide(b,6,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")).doubleValue());
// System.out.println("a/b="+a.divide(b,11).doubleValue()); //不指定舍入方式,报错“Invalid rounding mode” int mytt= 100;//整数可以随意初始化
BigDecimal oirginC = new BigDecimal(Integer.toString(mytt));
BigDecimal oirgin2 = new BigDecimal(mytt);
System.out.println("oirginC:"+oirginC);
System.out.println("oirgin2:"+oirgin2); BigDecimal scale = new BigDecimal("0.002");//小数必须用string, 否则会出现误差,如double
double testfloat=0.001;
BigDecimal scale2 = new BigDecimal(testfloat);
System.out.println(scale);
System.out.println(scale2);//输出为近似数0.001000000000000000020816681711721685132943093776702880859375 System.out.println(scale.equals(scale2));//两个比较对象必须在相同尺度才能用equal,2.0和2.00不相等,所以要用compare
System.out.println(scale.compareTo(scale2));//输出中,小于、等于、大于分别对应-1、0、1。可以用与不同尺度scale的对象,只要值相等就行了,如1.0等于1.00
if(0 == b.compareTo(new BigDecimal("3.00"))){//不同尺度的数
System.out.println("equal");
} //bigDecimal乘法运算返回int类型
System.out.println("multipy:"+oirginC.multiply(scale).intValue());
//bigDecimal加法运算返回int类型
System.out.println("add:"+b.add(a).doubleValue());
//bigDecimal减法运算返回int类型
System.out.println("substract:"+b.subtract(new BigDecimal(3.00)).doubleValue()); //Math.ceil()向上取整,就是小数不为0则整数加1舍去小数
int test1 =3;
double test2=0.01;
System.out.println(Double.valueOf(Math.ceil(test1 * test2)).intValue());
System.out.println(Math.ceil(1.02)); }
}

java中小数的处理:高精度运算用bigDecimal类,精度保留方法,即舍入方式的指定的更多相关文章

  1. Java中FTPClient上传中文目录、中文文件名乱码问题解决方法【好用】

    转: Java中FTPClient上传中文目录.中文文件名乱码问题解决方法 问题描述: 使用org.apache.commons.net.ftp.FTPClient创建中文目录.上传中文文件名时,目录 ...

  2. java 中利用反射机制获取和设置实体类的属性值

    摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...

  3. 将java中Map对象转为有相同属性的类对象(json作为中间转换)

    java中Map对象转为有相同属性的类对象(json作为中间转换) 准备好json转换工具类 public class JsonUtil { private static ObjectMapper o ...

  4. Java中的集合&lpar;十四&rpar; Map的实现类LinkedHashMap

    Java中的集合(十四) Map的实现类LinkedHashMap 一.LinkedHashMap的简介 LinkedHashMap是Map接口的实现类,继承了HashMap,它通过重写父类相关的方法 ...

  5. Java中小数精度问题

    代码如下:主要是利用java中写好的DecimalFormat类进行设置(#,0,%) import java.text.DecimalFormat; import java.util.Arrays; ...

  6. Java中Byte类型数据在运算中的问题

    比如: byte a=1; byte b=2; byte c; c=a+b; //这样是计算不出c,是错误的 c=a+1; //这样也是不能计算c的 c=64+1; //为什么这样就能计算c,在Jav ...

  7. Java中小数保留问题

    方式一: 四舍五入   double   f   =   111231.5585;   BigDecimal   b   =   new   BigDecimal(f);   double   f1  ...

  8. Java中的BigDecimal类精度问题

    bigdecimal 能保证精度的原理是:BigDecimal的解决方案就是,不使用二进制,而是使用十进制(BigInteger)+小数点位置(scale)来表示小数,就是把所有的小数变成整数,记录小 ...

  9. java中商业数据计算时用到的类BigDecimal和DecimalFormat

    1.引言 借用<Effactive Java>这本书中的话,float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确 ...

随机推荐

  1. Ubuntu不显示壁纸,桌面右键无反应解决

    用ubuntu tweak调整ubuntu的桌面图标显示,导致桌面无法显示壁纸,桌面点击右键无发应。 解决办法:Ubuntu Tweak中“调整”选项卡-》”显示桌面图标“的选项一定要打开,处于ON状 ...

  2. codeforces 165D&period;Beard Graph 解题报告

    题意: 给一棵树,树的每条边有一种颜色,黑色或白色,一开始所有边均为黑色,有两个操作: 操作1:将第i条边变成白色或将第i条边变成黑色. 操作2 :询问u,v两点之间仅经过黑色变的最短距离. 树链剖分 ...

  3. windows使用nginx&plus;memcached实现负载均衡和session或者缓存共享

    windows使用nginx+memcached实现负载均衡和session或者缓存共享 两台server server1:115.29.186.215 windows2008 64位操作系统 ser ...

  4. Cookie概念

    ASP.NET Cookie概念.CURD操作.原理.实际运用   会话就WEB开发来说,一个会话就是你通过浏览器与服务器之间的一次通话,只不过这种通话是以用浏览器浏览的方式来实现的. 就会话的应用来 ...

  5. 永久设置mysql中文乱码问题

    1.进入mysql的命令窗口 输入 show variables like '%char%'; 查看当前编码是否为UTF-8 2.在上述命令的结果中我们可以看到Wamp的安装目录,找到这一目录,在里面 ...

  6. 【Spring源码解读】bean标签中的属性(二)你可能还不够了解的 abstract 属性和 parent 属性

    abstract 属性说明 abstract 在java的语义里是代表抽象的意思,用来说明被修饰的类是抽象类.在Spring中bean标签里的 abstract 的含义其实也差不多,表示当前bean是 ...

  7. &lbrack;UGUI&rsqb;帧动画

    ImageFrameAnimation.cs using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; [R ...

  8. Spiral Matrix leetcode java

    题目: Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spira ...

  9. QT显示中文 连接上文

    1.首先是建立Linux开发环境1.1.在windowsXP下安装博创公司提供的虚拟机软件VMware Workstation,版本为VMware-workstation-full-7.0.1-227 ...

  10. ZOJ 17届校赛 Knuth-Morris-Pratt Algorithm&lpar; 水题&rpar;

    In computer science, the Knuth-Morris-Pratt string searching algorithm (or KMP algorithm) searches f ...