问题背景
我们在日常的开发处理中通常会遇到一个问题:无法确定小数点经过多少0才会出现有效数字,比如:0.00097213,就是再三个零之后才出现了9这个有效数字,而:0.1234就是直接出现了有效数字。而对于数字我们大部分情况都是要保留多少位数字,比如保留三位进行处理。这里的处理一般有入库操作或者制作一些数据看板或报表,总不可能有的数字拖拉很长,有的数字无限循环吧。
解决思路
对于小数的整体情况来观察的话,可以将小数总结为,在n个零之后出现有效数字,且有效数字个数大于零。
最为直观的方法就是正则匹配的形式,根据上述总结情况,写一个在小数点或0之后,查找第一个出现的1道9的数字的正则表达式来找第一个不为0的数字。以下是代码:
public static Double decimalProcessing(double decimal) {
BigDecimal decimalValue = new BigDecimal(String.valueOf(decimal));
String decimalString = String.valueOf(decimal);
Pattern pattern = Pattern.compile("(?<=(\\.|0))([1-9])");
Matcher matcher = pattern.matcher(decimalString);
int firstNonZeroPosition = 0;
if (matcher.find()) {
firstNonZeroPosition = matcher.start(2) - matcher.start(1);
}
MathContext mc = new MathContext(firstNonZeroPosition + 2);
BigDecimal processedDecimal = decimalValue.divide(BigDecimal.ONE, mc);
return processedDecimal.doubleValue();
}
首先将小数转换为BIgDecimal类型,方便进行更为精确的浮点数计算和舍入操作,然后转化为字符串后,使用写好的正则来进行匹配。
找到第一个不为0的数字的位置之后,使用match.start()来计算第一个非零数字相对于小数点的位置,然后依据此位置创建一个MathContext实例来指定保留的有效数字位数,这里我们设置的为3位,所以就是+3的操作。
最后使用divide将小数除以1并使用MathContext进行舍入,最后类型转换将数字输出。
这样我们就完成了对小数点后的有效数字保留三位并进行了四舍五入的处理。