如何实现小数位含多个5时向下取整?两位小数自定义取整需求
实现特殊规则的两位小数取整逻辑
针对你需要的特殊取整规则——保留两位小数时,仅当小数点后第三位及之后全部为5才向下取整,否则按正常四舍五入处理,Java自带的RoundingMode.HALF_DOWN确实无法满足需求(它会将所有第三位为5的数值进位,比如1.555会被舍入为1.56)。以下是可直接使用的自定义实现方案:
核心思路
通过字符串匹配判断小数点后两位之后的所有数字是否全为5:
- 如果是全5,使用
RoundingMode.DOWN向下取整到两位小数 - 否则,使用
RoundingMode.HALF_UP执行正常四舍五入
选择字符串处理而非纯数学计算,是为了避免浮点数精度丢失导致的判断误差(比如部分十进制小数无法在二进制中精确表示)。
代码实现
import java.math.BigDecimal; import java.math.RoundingMode; import java.util.regex.Pattern; public class CustomDecimalRounder { // 正则匹配:小数点后两位之后全是5的数字 private static final Pattern ALL_FIVES_PATTERN = Pattern.compile("^\\d+\\.\\d{2}(5+)$"); public static BigDecimal roundWithSpecialRule(BigDecimal number) { if (number == null) { throw new IllegalArgumentException("Number cannot be null"); } // 处理负数:先取绝对值计算,最后恢复符号 boolean isNegative = number.signum() < 0; BigDecimal absNum = number.abs(); // 转换为普通字符串,避免科学计数法干扰正则匹配 String numStr = absNum.toPlainString(); boolean isAllFivesAfterThird = ALL_FIVES_PATTERN.matcher(numStr).matches(); BigDecimal rounded; if (isAllFivesAfterThird) { // 全为5时向下取整 rounded = absNum.setScale(2, RoundingMode.DOWN); } else { // 其他情况正常四舍五入 rounded = absNum.setScale(2, RoundingMode.HALF_UP); } return isNegative ? rounded.negate() : rounded; } // 测试用例 public static void main(String[] args) { System.out.println(roundWithSpecialRule(new BigDecimal("1.555555555"))); // 输出 1.55 System.out.println(roundWithSpecialRule(new BigDecimal("1.555555556"))); // 输出 1.56 System.out.println(roundWithSpecialRule(new BigDecimal("1.555555551"))); // 输出 1.55 System.out.println(roundWithSpecialRule(new BigDecimal("1.555"))); // 输出 1.55 System.out.println(roundWithSpecialRule(new BigDecimal("1.556"))); // 输出 1.56 System.out.println(roundWithSpecialRule(new BigDecimal("-1.555555555")));// 输出 -1.55 } }
关键细节说明
- 正则表达式:
^\\d+\\.\\d{2}(5+)$确保匹配的是整数部分+小数点+两位小数+连续的5,覆盖了所有符合“第三位及之后全为5”的场景。 - BigDecimal的使用:全程用
BigDecimal而非double/float,彻底避免浮点数精度问题。 - 负数处理:通过取绝对值后处理再恢复符号,保证负数场景下的取整逻辑与正数一致(比如
-1.555555555会被舍入为-1.55而非-1.56)。
内容的提问来源于stack exchange,提问作者Articlaus
相关产品推荐
相关产品推荐

