真正的java的四舍五入
来源:互联网 发布:中国空运交通运输网络 编辑:程序博客网 时间:2024/05/21 19:24
下面列举让你惊讶的现象,或许你还一直这么用:
1、使用Math.round()
double d = 1041.735; d = Math.round(d*100)/100.0; //除以100.0 而不是100 System.out.println(d); //输出结果是1041.73
2、使用 BigDecima
double d = 9.655; BigDecimal b = new BigDecimal(d); d = b.setScale(2,RoundingMode.HALF_UP).doubleValue(); System.out.println(d); //输出结果是9.65
3、使用DecimalFormat
double d = 11.225;DecimalFormat df = new DecimalFormat("0.00");String s = df.format(d);System.out.println(s);//输出结果是11.22
所有的根源都是double的浮点运算机制
例1
1041.735*100=104173.49999999999Math.round(1041.735*100)=104173
例2
在进行使用double的构造函数之后,发生了变化,导致后续的四舍五入错误
例3
和例1、例2有点区别,在内部实现时,也是进行了相关的浮点预算
综上所述:只要进行浮点运算,就可能产生精度问题
上述例2和例3几乎接近真实,只需要进行一点调整即可
例2
double d = 9.655; //通过改变构造方法,就可以解决精度丢失问题 BigDecimal b = new BigDecimal(Double.toString(d)); d = b.setScale(2,RoundingMode.HALF_UP).doubleValue(); System.out.println(d); //输出结果是9.66
例3
double d = 11.225;DecimalFormat df = new DecimalFormat("0.00");//指定RoundingMode df.setRoundingMode(RoundingMode.HALF_UP);String s = df.format(d);System.out.println(s);//输出结果是11.23
下面我们再来看一个经典的例子
计算199999.00*0.015,结果保留2位有效数字
理论上 199999.00*0.015=2999.985
实际上java的bouble运算是 199999.00*0.015=2999.984999….
下面提供了一个double运算的工具类,最后的format解决了科学计数法显示问题(1.53E10)
public class DoubleUtil { private static final int DIV_SCALE=10;//默认除法运算精度 private DoubleUtil(){ } /** * 提供精确的加法运算 * @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 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 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(); } /** * 提供(相对)精确的除法运算 * 当除不尽时,使用默认精度:DIV_SCALE * @param v1 被除数 * @param v2 除数 * @return 两个参数的商 */ public static double div(double v1,double v2){ return div(v1,v2,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("scale不能小于0"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精确的小数位四舍五入处理 * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static double round(double v1,int scale){ if(scale<0){ throw new IllegalArgumentException("scale不能小于0"); } BigDecimal b = new BigDecimal(Double.toString(v1)); BigDecimal one = new BigDecimal("1"); return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } public static String format(double v1,int scale){ String s = String.valueOf(round(v1,scale)); s = new BigDecimal(s).toPlainString();//解决科学计算法转换问题 int k = s.indexOf("."); if(k<0 && scale>0){ s = s+".0"; k=s.indexOf("."); } if(k>0){ int d_scale = (s.length()-(k+1)); if(scale>d_scale){ for(int i=0;i<scale-d_scale;i++){ s+="0"; } }else if(scale<d_scale){//当scale=0时才会出现这种情况 s = s.substring(0,k); } } return s; }}
1 0
- 真正的java的四舍五入
- C#如何做到真正的四舍五入
- Java的四舍五入
- java的四舍五入
- java的四舍五入
- 【Java】 四舍五入的方法
- java的四舍五入
- java的四舍五入
- java的四舍五入
- java的四舍五入
- java的四舍五入
- Java的四舍五入
- java的四舍五入操作
- Java里的四舍五入
- 关于Java的四舍五入
- Java的四舍五入
- java实现精确的"四舍五入"
- java取四舍五入的方法
- 空闲时间学一个Linux命令(10)—— cat 命令
- 面向接口编程(1)--思想基础
- Object_C内存管理
- 初识Spring Boot框架
- configure Spring Data JPA by using XML
- 真正的java的四舍五入
- Python smtplib发送邮件 包含文本、附件、图片等
- Spring 配置 druid数据库连接
- Linux双网卡bonding操作方法
- 关于SCSS入门功能(上)
- ZCMU-1158-二叉树
- [modules] -- 设置别名,生成模块
- 【Java】HttpClient 使用(代码整理)
- coredump相关