You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现小数位含多个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
    }
}

关键细节说明

  1. 正则表达式:^\\d+\\.\\d{2}(5+)$确保匹配的是整数部分+小数点+两位小数+连续的5,覆盖了所有符合“第三位及之后全为5”的场景。
  2. BigDecimal的使用:全程用BigDecimal而非double/float,彻底避免浮点数精度问题。
  3. 负数处理:通过取绝对值后处理再恢复符号,保证负数场景下的取整逻辑与正数一致(比如-1.555555555会被舍入为-1.55而非-1.56)。

内容的提问来源于stack exchange,提问作者Articlaus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 04:36:13