java

tiger

常用链接

统计

my Blogs

最新评论

java取四舍五入的方法

“带下划线内容无效"

两种不同方法的实现:


1:
/**

* 提供小数位四舍五入处理。

* @param v 需要四舍五入的数字

* @param scale 小数点后保留几位

* @return 四舍五入后的结果

*/

public static double round(double v,int scale){
String temp="#,##0.";
for (int i=0;i<scale ;i++ )
{
temp+="0";
}
return Double.valueOf(new java.text.DecimalFormat(temp).format(v));
}

2:数学方法
public static double round2(double d, int scale) {
long temp=1;
for (int i=scale; i>;0; i--) {
temp*=10;
}
d*=temp;
long dl=Math.round(d);
return (double)(dl)/temp;
}

 

鉴于网友的的指出,我重新认真研究了一下四舍五入,最终给出正确解法如下:

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
* 本例通过对网上几种取四舍五入的研究,进行了一一测试。最终通过实验和理论得出round4为唯一正确的算法。
* 2008/10/13

* @author jamezhan
*
*/
public class RoundTest {

public static double round1(double v, int scale) {
if (scale < 0)
return v;

String temp = "#####0.";
for (int i = 0; i < scale; i++) {
temp += "0";
}

return Double.valueOf(new java.text.DecimalFormat(temp).format(v));
}

/**
* 该算法会出现中间运算后结果超过Double.MAX_VALUE,所以不推荐使用
* @param d
* @param scale
* @return
* @throws Exception
*/
public static double round2(double d, int scale) throws Exception {
if (scale < 0)
return d;

long temp = 1;
for (int i = scale; i > 0; i--) {
temp *= 10;
}

if (Math.abs(d * temp) > Double.MAX_VALUE)
throw new Exception("data is too big or too small");

d *= temp;
long dl = Math.round(d);
return (double) (dl) / temp;
}

public static double round3(double v, int scale) {
BigDecimal value = new BigDecimal(v);
float actualTax = value.setScale(scale, BigDecimal.ROUND_HALF_UP).floatValue();
return actualTax;
}

public static double round4(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));
BigDecimal one = new BigDecimal("1");
return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}

public static void testRound1(double d, int scale) {
System.out.println("==========================");
System.out.println("data:"+ d + "; scale:"+scale);
double a = round1(d, scale);
System.out.println(a);

DecimalFormat df = new DecimalFormat();
System.out.println("formatted:"+df.format(a));
}

public static void testRound2(double d, int scale) {
try {
System.out.println("==========================");
System.out.println("data:"+ d + "; scale:"+scale);
double a = round2(d, scale);
System.out.println(a);

DecimalFormat df = new DecimalFormat();
System.out.println("formatted:"+df.format(a));
} catch (Exception e) {
System.err.println( e.getMessage() );
}
}

public static void testRound3(double d, int scale) {
try {
System.out.println("==========================");
System.out.println("data:"+ d + "; scale:"+scale);
double a = round3(d, scale);
System.out.println(a);

DecimalFormat df = new DecimalFormat();
System.out.println("formatted:"+df.format(a));
} catch (Exception e) {
System.err.println( e.getMessage() );
}
}

public static void testRound4(double d, int scale) {
try {
System.out.println("==========================");
System.out.println("data:"+ d + "; scale:"+scale);
double a = round4(d, scale);
System.out.println(a);

DecimalFormat df = new DecimalFormat();
System.out.println("formatted:"+df.format(a));
} catch (Exception e) {
System.err.println( e.getMessage() );
}
}


public static void main(String[] args) throws Exception {
System.out.println("****************************** Test round1 ******************************");

testRound1(Double.MAX_VALUE,2);
testRound1(1.264,2);
testRound1(-1.264,2);
testRound1(1.265,2);//wrong result
testRound1(-1.265,2);//wrong result
testRound1(1.266,2);
testRound1(-1.266,2);
testRound1(10224948.265,2);//wrong result
testRound1(-10224948.265,2);//wrong result
testRound1(-Double.MAX_VALUE, 2);

System.out.println("****************************** Test round2 ******************************");

testRound2(Double.MAX_VALUE,2);
testRound2(1.264,2);
testRound2(-1.264,2);
testRound2(1.265,2);//wrong result (java表示小数0.1的问题导致的 1.265表示为1.2599999904632568)
testRound2(-1.265,2);//wrong result (由于round算法是先加0.5再运算,所以d为负数时且最后一位小数为5时结果是不正确的)
testRound2(1.266,2);
testRound2(-1.266,2);
testRound2(10224948.265,2);
testRound2(-10224948.265,2);//wrong result
testRound2(-Double.MAX_VALUE, 2);


System.out.println("****************************** Test round3 ******************************");

testRound3(Double.MAX_VALUE,2);//wrong result 
testRound3(1.264,2);
testRound3(-1.264,2);
testRound3(1.265,2);
testRound3(-1.265,2);
testRound3(1.266,2);
testRound3(-1.266,2);
testRound3(10224948.265,2);//wrong result 
testRound3(-10224948.265,2);//wrong result
testRound3(-Double.MAX_VALUE, 2);//wrong result 

System.out.println("****************************** Test round4 ******************************");

testRound4(Double.MAX_VALUE,2);
testRound4(1.264,2);
testRound4(-1.264,2);
testRound4(1.265,2);
testRound4(-1.265,2);
testRound4(1.266,2);
testRound4(-1.266,2);
testRound4(10224948.265,2);
testRound4(-10224948.265,2);
testRound4(-Double.MAX_VALUE, 2);

}
}


 

posted on 2006-04-25 11:38 翠竹 阅读(12850) 评论(6)  编辑  收藏 所属分类: java

评论

# re: java取四舍五入的方法 2006-05-30 14:26 rick

呵呵,和我的大同小异:
private double round2(double va) {
// -------->运算四舍五入保留小数点2位
va=Math.round(va*100.0);
return va/100;
}

private double trunc2(double va){
// -------->运算截断保留小数点2位
va=Math.floor(va*100.0);
return va/100;
}  回复  更多评论   

# re: java取四舍五入的方法 2006-06-14 10:05 翠竹

呵呵,就是!  回复  更多评论   

# re: java取四舍五入的方法 2007-03-24 21:18 我贼帅

楼主的算法不错,你的只适合两位小数...  回复  更多评论   

# re: java取四舍五入的方法 2007-04-16 08:52 翠竹

可以支持多位:@param scale 小数点后保留几位   回复  更多评论   

# re: java取四舍五入的方法 2007-09-19 09:21 longxibo

lz有bug
round(-10224948.26, 2)出问题
round2一样  回复  更多评论   

# re: java取四舍五入的方法 2008-10-13 15:27 翠竹

@longxibo
对了,请你用round4方法。谢谢!!  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: