java四舍五入
原文地址:https://blog.csdn.net/qwfylwc/article/details/53939906
下面列举让你惊讶的现象,或许你还一直这么用:
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
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.49999999999
Math.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 p(double v1,double v2){
return p(v1,v2,DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算
* 当除不尽时,使用参数scale指定精度,进行四舍五入
* @param v1 被除数
* @param v2 除数
* @param scale 表示精确到小数点后几位
* @return 两个参数的商
*/
public static double p(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.pide(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.pide(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;
}
}
相关阅读
系统版本:Win10 64位JDK版本:jdk1.8.0_171开发工具:Eclipse 问题描述:在cmd中使用命令java HelloWorld时,提示“找不到或无法加载主类
-XX:PermSize/-XX:MaxPermSize,永久代内存; 1. 虚拟机参数:-ea,支持 assert 断言关键字 eclipse 默认是不开启此参数的,也就是虽然
每次写代码都要查找,所以就放这里面备份了 基本pom引用: <dependency> <groupId>org.apache.httpcompone
JavaScript之Style对象与CurrentStyle对象
1、Style对象 style对象代表一个单独的样式声明,可以从应用样式的文档元素访问Style对象。style对象获取的是内联样式,即元素标签
JAVAWEB开发之工作流详解(一)——Activiti的环境搭建
工作流的概念 工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按