当前位置: 首页 > 图灵资讯 > 技术篇> RoundingMode 几个参数详解

RoundingMode 几个参数详解

来源:图灵教育
时间:2023-06-18 09:26:50

第一版

java.math.RoundingMode 详解几个参数

java.math.RoundingMode中有几个参数让我有点头晕,现在用个人的理解来总结一下:

为了更好地理解,我们可以画一个XY轴

RoundingMode.CEILING:取右边最近的整数

RoundingMode.DOWN:去掉小数取整,即正数取左,负数取右,相当于向原点靠近的方向取整

RoundingMode.FLOOR:取左边最近的正数

RoundingMode.HALF_DOWN:五舍六入,负数先取绝对值,五舍六入再负数

RoundingMode.HALF_UP:四舍五入,负数原理同上

RoundingMode.HALF_EVEN:这个比较绕,如果整数是奇数,四舍五入,如果偶数是五舍六入

第二版

roundmode是指舍位时的模式,传输参数时使用BigDecimal.ROUND_XXXX_XXX,

以下例子是setscale(0,BigDecimal.ROUND_XXXX_XXX));如果保留小数位数不是零,例如

setScale(2,BigDecimal.ROUND_XXXX_XXX)); 是 2 ,这个数字的小数位数应该大于2位。第三个是选择得位。

ROUND_CEILING: 向无限方向移动 1.1->2 1.5->2 1.8->2 -1.1->-1 -1.5->-1 -1.8->-1

ROUND_DOWN:1.1.1向0方向移动->1 1.5->1 1.8->1 -1.1->-1 -1.5->-1 -1.8>-1

ROUND_FLOOR:与CEILING相反,负无限 1.1->1 1.5->1 1.8->1 -1.1->-2 -1.5->-2 -1.8->-2

ROUND_HALF_DOWN:以5为分界线,或五舍六入1.5->1 1.6->1 -1.5->-1 -1.6->-2 1.15->1.1 1.16->1.2 1.55->1.6 1.56->1.6

ROUND_HALF_EVEN:以5为分界线,如果是5,则前一个变偶数为1.15->1.2 1.16->1.2 1.25->1.2 1.26->1.3

ROUND_HALF_UP:最常见的四舍五入

ROUND_UNNECESSARY:无需舍位

ROUND_UP:ROUND_DOWN,1.1远离0的方向->2 1.5->2 1.8->2 -1.1->-2 -1.5->-2 -1.8->-2

具体精确到几个位置,因此应该使用它

商=被除数.devide(除数,保留小数位数,方法准确)

第三版

BigDecimal 整数非标度值由任意精度计算 和 32 位的整数标度 (scale) 组成。若为零或正数,则标度为小数点后的位数。若为负数,则将该数的非标度值乘以 10 的负 scale 次幂。所以,BigDecimal 表示的值是 (unscaledValue × 10-scale)。

浮点数运算可以处理任何长度。

BigDecimal add(BigDecimal val) //BigDecimal 加法

BigDecimal subtract (BigDecimal val) //BigDecimal 减法

BigDecimal multiply (BigDecimal val) //BigDecimal 乘法

BigDecimal pide (BigDecimal val,RoundingMode mode) 除法

具体使用 计算:

  

  加: a.add(b);

  减: a.subtract(b);

  乘: a.multiply(b);

  除: a.pide(b,2);//2是精度取值

除法细解:

//注意以下相除会抛出异常的原因: 通过BigDecimal的pide方法进行除法时,当出现无限循环小数时,就会抛出异常

//BigDecimal pideBg = a.pide(b);

//解决方案是:设置精度;是为pide设置精确的小数点

pide(xxxxx,2, BigDecimal.ROUND_HALF_EVEN)

//其中第二个参数表示:保留小数点后有多少位?

BigDecimal不整除抛出异常,请设置精度!

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

at java.math.BigDecimal.pide(BigDecimal.java:1278)

at main.Main.main(Main.java:41)

让我们来看看除法的详细说明:

pide(BigDecimal pisor, int scale, introundingMode)

BigDecimalsetScale方法

BigDecimal.setScale()

格式化小数点的方法

这意味着保留一个小数,默认情况下四舍五入

setScale(1)

如果2.35会变成2.35,直接删除多余的小数位 setScale(1,BigDecimal.ROUND_DOWN)

2.35变成2.4 setScale(1,BigDecimal.ROUND_UP)

四舍五入,2.35变成2.4 setScale(1,BigDecimal.ROUND_HALF_UP)

四舍五入,2.35变成2.3,如果是5则向下舍setScaler(1)BigDecimal.ROUND_HALF_DOWN)

注意点一

scale指的是你小数点后的位数。

scale()是BigDecimal类的方法。例如

BigDecimal b = new BigDecimal("123.456");

b.scale()返回是3

注意二roundingMode是小数的保留模式。它们都是BigDecimal中的常量字段,

有很多种,比如

BigDecimal.ROUND_HALF_UP表示4舍5入

注意点三

pide(BigDecimal pisor, int scale, introundingMode)意思是说:

我用bigdecimal对象除以pisor后的结果,并要求结果保留scale的小数位。roundingmode表示保留模式是什么,是四舍五入还是其他?

BigDecimal aa = new BigDecimal(135.95 );

BigDecimal bb=new BigDecimal("100" );

BigDecimal result=aa.multiply(bb); //做加法

3.java中 BigDecimal类型可转换为double类型:

用 变量.doubleValue();函数 即可将 BigDecimal 类型数据 转化为 double类型!

4.java BigDecimal比较大小

可通过BigDecimalcompareto方法进行比较。

返回的结果是int类型,-1小于,0等于,1大于。

下面的例子:

BigDecimal a = new BigDecimal("1.00");

BigDecmial b = new BigDecimal(1);

想比较a和b的大小,通常使用equals

System.out.println(a.equals(b));

但输出结果如下:false

原因是:BigDecimal比较时,不仅比较值,而且精度更高?

if(a.compareTo(b)==0) 结果是true

比较大小可以用 a.compareTo(b)

返回值 -1 小于 0 等于 1 大于

5.BigDecimal取最大、最小、绝对、相反的数字:

  a.max (b) //比较最大值

  a.min(b) //比较最小值

  a.abs()//取最绝对值

  a.negate()//取相反数

6.以下是注意事项 :

BigDecimal枚举常量 :

CEILING

向正无限大方向放弃的放弃模式。

DOWN

舍入模式向零方向。

FLOOR

舍入到负无限大方向的模式。

HALF_DOWN

如果向最接近数字方向的舍入模式等于两个相邻数字的距离,则向下舍入。

HALF_EVEN

舍入模式最接近数字方向,如果与两个相邻数字的距离相等,则舍入相邻偶数。

HALF_UP

如果向最接近数字方向的舍入模式等于两个相邻数字的距离,则向上舍入。

UNNECESSARY

具有准确结果的舍入模式用于断言请求的操作,因此不需要舍入。

UP

远离零方向舍入的舍入模式。

7.关于BigDecimal的格式化

public String formatValue(Object value){

String content = null;

if (value == null) {

content = "";

} else {

if(value instanceof BigDecimal){

//conver to fortmat String

NumberFormat nf = NumberFormat.getInstance();

nf.setMinimumFractionDigits(2);

nf.setMaximumFractionDigits(2);

content = nf.format(value);

}else{

content = String.valueOf(value);

}

}

return content;

}

使用这种方法可以达到格式化的效果,包括value instanceof BigDecimal,当字符类型为BigDecimal类型时,这里的NumberFormat表示字符类型,以下两个代码表示小数点后面的精确位数。

还有两种类型的NumberFormat:

getCurrencyInstance(): 回到目前的默认状态 货币格式的环境

CurrencyInstance(): 返回指定语言 环境的数字格式一般是百分比格式

8.在《Effective Java》本书还提到了这一原则。float和double只能用于科学计算或工程计算。我们应该在商业计算中使用java.math.BigDecimal。

如果我们需要精确计算,我们必须使用String来制造BigDecimal!

下面的工具类是转载他人的,可以通过工具类实现小数的精确计算。

1import java.math.BigDecimal;

2/** *//**

3* 由于Java的简单类型无法准确计算浮点数,因此提供了精确的工具类别

4* 浮点数运算确实包括加减乘除和四舍五入。

5*/

6public class Arith{

7 ////默认除法操作精度

8 private static final int DEF_DIV_SCALE = 10;

9 ///这一类不能实例化

10 private Arith(){

11 }

12

13 /** *//**

14 * 提供准确的加法操作。

15 * @param v1 被加数

16 * @param v2 加数

17 * @return 两个参数的和

18 */

19 public static double add(double v1,double v2){

20 BigDecimal b1 = new BigDecimal(Double.toString(v1));

21 BigDecimal b2 = new BigDecimal(Double.toString(v2));

22 return b1.add(b2).doubleValue();

23 }

24 /** *//**

25 * 提供精确的减法操作。

26 * @param v1 被减数

27 * @param v2 减数

28 * @return 两个参数之间的差异

29 */

30 public static double sub(double v1,double v2){

31 BigDecimal b1 = new BigDecimal(Double.toString(v1));

32 BigDecimal b2 = new BigDecimal(Double.toString(v2));

33 return b1.subtract(b2).doubleValue();

34 }

35 /** *//**

36 * 提供准确的乘法操作。

37 * @param v1 被乘数

38 * @param v2 乘数

39 * @return 两个参数的积累

40 */

41 public static double mul(double v1,double v2){

42 BigDecimal b1 = new BigDecimal(Double.toString(v1));

43 BigDecimal b2 = new BigDecimal(Double.toString(v2));

44 return b1.multiply(b2).doubleValue();

45 }

46

47 /** *//**

48 * 提供(相对)精确的除法操作,当发生无穷无尽的情况时,精确到

49 * 小数点后10位,未来数字四舍五入。

50 * @param v1 被除数

51 * @param v2 除数

52 * @return 两个参数的商家

53 */

54 public static double p(double v1,double v2){

55 return p(v1,v2,DEF_DIV_SCALE);

56 }

57

58 /** *//**

59 * 提供(相对)精确的除法操作。当发生无穷无尽的情况时,scale参数是指

60 * 定精度,以后的数字四舍五入。

61 * @param v1 被除数

62 * @param v2 除数

63 * @param scale 表示需要精确到小数点以后的几位。

64 * @return 两个参数的商家

65 */

66 public static double p(double v1,double v2,int scale){

67 if(scale<0){

68 throw new IllegalArgumentException(

69 "The scale must be a positive integer or zero");

70 }

71 BigDecimal b1 = new BigDecimal(Double.toString(v1));

72 BigDecimal b2 = new BigDecimal(Double.toString(v2));

73 return b1.pid(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();

74 }

75

76 /** *//**

77 * 四舍五入提供精确的小数位处理。

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

79 * @param scale 小数点后保留几个

80 * @return 四舍五入后的结果

81 */

82 public static double round(double v,int scale){

83 if(scale<0){

84 throw new IllegalArgumentException(

85 "The scale must be a positive integer or zero");

86 }

87 BigDecimal b = new BigDecimal(Double.toString(v));

88 BigDecimal one = new BigDecimal("1");

89 return b.pid(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();

90 }

91 }BigDecimal 整数非标度值由任意精度计算 和 32 位的整数标度 (scale) 组成。若为零或正数,则标度为小数点后的位数。若为负数,则将该数的非标度值乘以 10 的负 scale 次幂。因此,BigDecimal 表示的值是 (unscaledValue × 10-scale)。

浮点数运算可以处理任何长度。

BigDecimal add(BigDecimal val) //BigDecimal 加法

BigDecimal subtract (BigDecimal val) //BigDecimal 减法

BigDecimal multiply (BigDecimal val) //BigDecimal 乘法

BigDecimal pide (BigDecimal val,RoundingMode mode) 除法

具体使用 计算:

  

  加: a.add(b);

  减: a.subtract(b);

  乘: a.multiply(b);

  除: a.pide(b,2);//2是精度取值

除法细解:

//注意以下相除会抛出异常的原因: 通过BigDecimal的pide方法进行除法时,当出现无限循环小数时,就会抛出异常

//BigDecimal pideBg = a.pide(b);

//解决方案是:设置精度;是为pide设置精确的小数点

pide(xxxxx,2, BigDecimal.ROUND_HALF_EVEN)

//其中第二个参数表示:保留小数点后有多少位?

BigDecimal不整除抛出异常,请设置精度!

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

at java.math.BigDecimal.pide(BigDecimal.java:1278)

at main.Main.main(Main.java:41)

让我们来看看除法的详细说明:

pide(BigDecimal pisor, int scale, introundingMode)

BigDecimalsetScale方法

BigDecimal.setScale()

格式化小数点的方法

这意味着保留一个小数,默认情况下四舍五入

setScale(1)

如果2.35会变成2.35,直接删除多余的小数位 setScale(1,BigDecimal.ROUND_DOWN)

2.35变成2.4 setScale(1,BigDecimal.ROUND_UP)

四舍五入,2.35变成2.4 setScale(1,BigDecimal.ROUND_HALF_UP)

四舍五入,2.35变成2.3,如果是5则向下舍setScaler(1)BigDecimal.ROUND_HALF_DOWN)

注意点一

scale指的是你小数点后的位数。

scale()是BigDecimal类的方法。例如

BigDecimal b = new BigDecimal("123.456");

b.scale()返回是3

注意二roundingMode是小数的保留模式。它们都是BigDecimal中的常量字段,

有很多种,比如

BigDecimal.ROUND_HALF_UP表示4舍5入

注意点三

pide(BigDecimal pisor, int scale, introundingMode)意思是说:

我用bigdecimal对象除以pisor后的结果,并要求结果保留scale的小数位。roundingmode表示保留模式是什么,是四舍五入还是其他?

BigDecimal aa = new BigDecimal(135.95 );

BigDecimal bb=new BigDecimal("100" );

BigDecimal result=aa.multiply(bb); //做加法

3.java中 BigDecimal类型可转换为double类型:

用 变量.doubleValue();函数 即可将 BigDecimal 类型数据 转化为 double类型!

4.java BigDecimal比较大小

可通过BigDecimalcompareto方法进行比较。

返回的结果是int类型,-1小于,0等于,1大于。

下面的例子:

BigDecimal a = new BigDecimal("1.00");

BigDecmial b = new BigDecimal(1);

想比较a和b的大小,通常使用equals

System.out.println(a.equals(b));

但输出结果如下:false

原因是:BigDecimal比较时,不仅比较值,而且精度更高?

if(a.compareTo(b)==0) 结果是true

比较大小可以用 a.compareTo(b)

返回值 -1 小于 0 等于 1 大于

5.BigDecimal取最大、最小、绝对、相反的数字:

  a.max (b) //比较最大值

  a.min(b) //比较最小值

  a.abs()//取最绝对值

  a.negate()//取相反数

6.以下是注意事项 :

BigDecimal枚举常量 :

CEILING

向正无限大方向放弃的放弃模式。

DOWN

舍入模式向零方向。

FLOOR

舍入到负无限大方向的模式。

HALF_DOWN

如果向最接近数字方向的舍入模式等于两个相邻数字的距离,则向下舍入。

HALF_EVEN

舍入模式最接近数字方向,如果与两个相邻数字的距离相等,则舍入相邻偶数。

HALF_UP

如果向最接近数字方向的舍入模式等于两个相邻数字的距离,则向上舍入。

UNNECESSARY

具有准确结果的舍入模式用于断言请求的操作,因此不需要舍入。

UP

远离零方向舍入的舍入模式。

7.关于BigDecimal的格式化

public String formatValue(Object value){

String content = null;

if (value == null) {

content = "";

} else {

if(value instanceof BigDecimal){

//conver to fortmat String

NumberFormat nf = NumberFormat.getInstance();

nf.setMinimumFractionDigits(2);

nf.setMaximumFractionDigits(2);

content = nf.format(value);

}else{

content = String.valueOf(value);

}

}

return content;

}

使用这种方法可以达到格式化的效果,包括value instanceof BigDecimal,当字符类型为BigDecimal类型时,这里的NumberFormat表示字符类型,以下两个代码表示小数点后面的精确位数。

还有两种类型的NumberFormat:

getCurrencyInstance(): 回到目前的默认状态 货币格式的环境

CurrencyInstance(): 返回指定语言 环境的数字格式一般是百分比格式

8.在《Effective Java》本书还提到了这一原则。float和double只能用于科学计算或工程计算。我们应该在商业计算中使用java.math.BigDecimal。

如果我们需要精确计算,我们必须使用String来制造BigDecimal!

下面的工具类是转载他人的,可以通过工具类实现小数的精确计算。

1import java.math.BigDecimal;

2/** *//**

3* 由于Java的简单类型无法准确计算浮点数,因此提供了精确的工具类别

4* 浮点数运算确实包括加减乘除和四舍五入。

5*/

6public class Arith{

7 ////默认除法操作精度

8 private static final int DEF_DIV_SCALE = 10;

9 ///这一类不能实例化

10 private Arith(){

11 }

12

13 /** *//**

14 * 提供准确的加法操作。

15 * @param v1 被加数

16 * @param v2 加数

17 * @return 两个参数的和

18 */

19 public static double add(double v1,double v2){

20 BigDecimal b1 = new BigDecimal(Double.toString(v1));

21 BigDecimal b2 = new BigDecimal(Double.toString(v2));

22 return b1.add(b2).doubleValue();

23 }

24 /** *//**

25 * 提供精确的减法操作。

26 * @param v1 被减数

27 * @param v2 减数

28 * @return 两个参数之间的差异

29 */

30 public static double sub(double v1,double v2){

31 BigDecimal b1 = new BigDecimal(Double.toString(v1));

32 BigDecimal b2 = new BigDecimal(Double.toString(v2));

33 return b1.subtract(b2).doubleValue();

34 }

35 /** *//**

36 * 提供准确的乘法操作。

37 * @param v1 被乘数

38 * @param v2 乘数

39 * @return 两个参数的积累

40 */

41 public static double mul(double v1,double v2){

42 BigDecimal b1 = new BigDecimal(Double.toString(v1));

43 BigDecimal b2 = new BigDecimal(Double.toString(v2));

44 return b1.multiply(b2).doubleValue();

45 }

46

47 /** *//**

48 * 提供(相对)精确的除法操作,当发生无穷无尽的情况时,精确到

49 * 小数点后10位,未来数字四舍五入。

50 * @param v1 被除数

51 * @param v2 除数

52 * @return 两个参数的商家

53 */

54 public static double p(double v1,double v2){

55 return p(v1,v2,DEF_DIV_SCALE);

56 }

57

58 /** *//**

59 * 提供(相对)精确的除法操作。当发生无穷无尽的情况时,scale参数是指

60 * 定精度,以后的数字四舍五入。

61 * @param v1 被除数

62 * @param v2 除数

63 * @param scale 表示需要精确到小数点以后的几位。

64 * @return 两个参数的商家

65 */

66 public static double p(double v1,double v2,int scale){

67 if(scale<0){

68 throw new IllegalArgumentException(

69 "The scale must be a positive integer or zero");

70 }

71 BigDecimal b1 = new BigDecimal(Double.toString(v1));

72 BigDecimal b2 = new BigDecimal(Double.toString(v2));

73 return b1.pid(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();

74 }

75

76 /** *//**

77 * 四舍五入提供精确的小数位处理。

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

79 * @param scale 小数点后保留几个

80 * @return 四舍五入后的结果

81 */

82 public static double round(double v,int scale){

83 if(scale<0){

84 throw new IllegalArgumentException(

85 "The scale must be a positive integer or zero");

86 }

87 BigDecimal b = new BigDecimal(Double.toString(v));

88 BigDecimal one = new BigDecimal("1");

89 return b.pid(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();

90 }

91 }