前段时间系统需要对大部分的数字进行处理,于是写了一个封装类。下面是参考网上资料进行的总结。
Java中对数字处理一般有3种方法。
1,数字的格式化一般用DecimalFormat
DecimalFormat 是 NumberFormat 的一个具体子类,用于格式化十进制数字。该类设计有各种功能,使其能够分析和格式化任意语言环境中的数,包括对西方语言、阿拉伯语和印度语数字的支持。它还支持不同类型的数,包括整数 (123)、定点数 (123.4)、科学记数法表示的数 (1.23E4)、百分数 (12%) 和金额 ($123)。所有这些内容都可以本地化。
DecimalFormat 包含一个模式 和一组符号
符号含义:
符号
位置
本地化?
含义
0
数字
是
阿拉伯数字
#
数字字
是
阿拉伯数字,如果不存在则显示为空
.
数字
是
小数分隔符或货币小数分隔符
-
数字
是
减号
,
数字
是
分组分隔符
E
数字
是
分隔科学计数法中的尾数和指数。在前缀或后缀中无需加引号。
;
子模式边界
是
分隔正数和负数子模式
%
前缀或后缀
是
乘以 100 并显示为百分数
/u2030
前缀或后缀
是
乘以 1000 并显示为千分数
¤(/u00A4)
前缀或后缀
否
货币记号,由货币符号替换。如果两个同时出现,则用国际货币符号替换。如果出现在某个模式中,则使用货币小数分隔符,而不使用小数分隔符。
'
前缀或后缀
否
用于在前缀或或后缀中为特殊字符加引号,例如 "'#'#" 将 123 格式化为 "#123"。要创建单引号本身,请连续使用两个单引号:"# o''clock"。
例子:
DecimalFormat df1 = new DecimalFormat("0.0");
DecimalFormat df2 = new DecimalFormat("#.#");
DecimalFormat df3 = new DecimalFormat("000.000");
DecimalFormat df4 = new DecimalFormat("###.###");
System.out.println(df1.format(12.34));
System.out.println(df2.format(12.34));
System.out.println(df3.format(12.34));
System.out.println(df4.format(12.34));
运行结果:
12.3
12.3
012.340
12.34
DecimalFormat format = new DecimalFormat("###,####.000");
System.out.println(format.format(111111123456.1227222));
Locale.setDefault(Locale.US);
DecimalFormat usFormat = new DecimalFormat("###,###.000");
System.out.println(usFormat.format(111111123456.1227222));
DecimalFormat addPattenFormat = new DecimalFormat();
addPattenFormat.applyPattern("##,###.000");
System.out.println(addPattenFormat.format(111111123456.1227));
DecimalFormat zhiFormat = new DecimalFormat();
zhiFormat.applyPattern("0.000E0000");
System.out.println(zhiFormat.format(10000));
System.out.println(zhiFormat.format(12345678.345));
DecimalFormat percentFormat = new DecimalFormat();
percentFormat.applyPattern("#0.000%");
System.out.println(percentFormat.format(0.3052222));
运行结果 :
1111,1112,3456.123
111,111,123,456.123
111,111,123,456.123
1.000E0004
1.235E0007
30.522%
如果使用具有多个分组字符的模式,则最后一个分隔符和整数结尾之间的间隔才是使用的分组大小。所以 "#,##,###,####" == "######,####" == "##,####,####"。
2,对数字精度要求比较高,一般用BigDecimal
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
(1)加减乘除
BigDecimal m1 = new BigDecimal(12);
BigDecimal m2 = new BigDecimal(5);
// 加
System.out.println(m1.add(m2));// 17
// 减
System.out.println(m1.subtract(m2));// 7
// 乘
System.out.println(m1.multiply(m2));// 60
// 除
System.out.println(m1.divide(m2, 2,BigDecimal.ROUND_HALF_UP));//2.40
(2)进度取舍
BigDecimal actualValue = new BigDecimal(StringUtil.isNotEmpty(wipRecipeDataVO.getActualValue()) ?
wipRecipeDataVO.getActualValue() : StringUtil.defaultString(wipRecipeDataVO.getValue()));
if(wipRecipeDataVO.getPrecision().length()==1) {
//四舍五入
actualValue = actualValue.setScale(Integer.parseInt(wipRecipeDataVO.getPrecision()), BigDecimal.ROUND_HALF_UP);
}else if(wipRecipeDataVO.getPrecision().startsWith("/")) {
//截取
actualValue = actualValue.setScale(Integer.parseInt(StringUtils.substringAfter(wipRecipeDataVO.getPrecision(),"/")), BigDecimal.ROUND_DOWN);
}else if(wipRecipeDataVO.getPrecision().startsWith("+")) {
////向上取舍
actualValue = actualValue.setScale(Integer.parseInt(StringUtils.substringAfter(wipRecipeDataVO.getPrecision(),"+")), BigDecimal.ROUND_CEILING);
}else {
throw new BusinessException("ERR-5027", new Object[] {wipRecipeDataVO.getWipEntityId().toString(),
wipRecipeDataVO.getName(), wipRecipeDataVO.getPrecision()});
}
参数定义
ROUND_CEILING
Rounding mode to round towards positive infinity.
向正无穷方向舍入
ROUND_DOWN
Rounding mode to round towards zero.
向零方向舍入
ROUND_FLOOR
Rounding mode to round towards negative infinity.
向负无穷方向舍入
ROUND_HALF_DOWN
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
ROUND_HALF_EVEN
Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP ,如果是偶数,使用ROUND_HALF_DOWN
ROUND_HALF_UP
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
ROUND_UNNECESSARY
Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary.
计算结果是精确的,不需要舍入模式
ROUND_UP
Rounding mode to round away from zero.
向远离0的方向舍入
3,处理对数字精度要求不高的用Math
Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;
Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;
Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数(这也是我们在数学课上学到的舍入规则)。
// Math.ceil(Double a)返回大于等于(>=a)的最大整数
System.out.println(Math.ceil(1.3));// 2.0
// Math.floor(Double a)返回小于等于(<=a)的最大整数
System.out.println(Math.floor(1.3));// 1.0
// Math.rint(Double a)返回离a最近的整数,如果同为整数且同样接近则取偶数
System.out.println(Math.rint(0.5));// 0.0
System.out.println(Math.rint(1.5));// 2.0
System.out.println(Math.rint(0.3));// 0.0
// Math.round(Double a)将参数(a+0.5)之后向下取整整数,
System.out.println(Math.round(1.4));// 1 加上0.5之后变成1.9向下取整等于1
System.out.println(Math.round(1.5));// 1 加上0.5之后变成2向下取整等于2
System.out.println(Math.round(1.6));// 2 加上0.5之后变成2.1向下取整等于2
System.out.println(Math.round(-1.4));// -1 加上0.5之后变成-0.9向下取整等于-1
System.out.println(Math.round(-1.5));// -1 加上0.5之后变成-1向下取整等于-1
System.out.println(Math.round(-1.6));// -2 加上0.5之后变成-1.1向下取整等于-2
// Math.max()取最大值
System.out.println(Math.max(1, 2));// 2
// Math.min()取最小值
System.out.println(Math.min(1, 2));// 2
// Math.abs()取绝对值
System.out.println(Math.abs(-100));// 100
// Math.random()产生0~1之间的double型数字
System.out.println(Math.random());// 结果等于(0<=Math.random()<1.0)