前端开发中如何实现复杂的数字格式化,包括小数点处理?

前端计算
1、5,512.1913 小数点第2位大于5的 向上取整,
2、173.544 小数点第2位小于5的 向小取整

1、5,512.1913 计算后 得到 5,512.20
2、173.544 计算后 得到 173.54

阅读 1.2k
avatarAI BotBETA

在前端开发中,实现复杂的数字格式化,包括小数点的处理,通常可以通过JavaScript的内置方法或第三方库来完成。对于你提到的具体需求,我们可以使用JavaScript的Math.round()函数结合一些字符串处理技巧来实现。但是,由于Math.round()默认是四舍五入到最接近的整数,我们需要对其进行调整以适应小数点后特定位置的取整逻辑。

解决方案

  1. 对于小数点第2位大于5的向上取整

    你可以先将数字乘以100(移动小数点两位),进行四舍五入后,再除以100(恢复小数点位置)。但这里为了“向上取整”,我们可以考虑使用Math.ceil()(总是向上取整)对乘以10后的数进行操作,然后再除以10。不过,由于是直接处理到小数点后第二位,我们需要稍微调整这个逻辑,先判断第二位是否大于5,如果是,则直接对乘以100的结果加1(如果已经是整数则无需加),再进行除法操作。

    function roundUpIfSecondDecimalGreaterThan5(num) {
        const parts = num.toString().split('.');
        if (parts.length < 2) return num; // 如果没有小数点,直接返回原数
        const intPart = parseInt(parts[0], 10);
        const decimalPart = parseFloat('0.' + parts[1]);
        const secondDecimal = Math.floor((decimalPart * 100) % 10);
        if (secondDecimal >= 5) {
            return (Math.floor(num * 100) + 1) / 100;
        }
        return num;
    }
    
    console.log(roundUpIfSecondDecimalGreaterThan5(5512.1913)); // 输出 5512.2

注意:这里为了简化处理,我直接将5,512.1913作为5512.1913处理,因为通常数字不会以逗号分隔千位。如果确实需要处理带逗号的数字字符串,你需要先将其转换为数值类型。

  1. 对于小数点第2位小于5的向小取整

    这个相对简单,直接使用toFixed(2)可以实现向小取整(实际上是四舍五入到小数点后两位,但由于我们只关心小于5的情况,所以这里直接使用即可)。

    function roundDownIfSecondDecimalLessThan5(num) {
        return parseFloat(num.toFixed(2));
    }
    
    console.log(roundDownIfSecondDecimalLessThan5(173.544)); // 输出 173.54

注意

  • 上述roundUpIfSecondDecimalGreaterThan5函数在处理极端情况时(如123.499),可能不会按预期工作,因为它仅检查第二位小数是否大于或等于5。如果需要更精确的控制(如四舍六入五成双等银行家舍入法),则需要更复杂的逻辑。
  • 对于带有千位分隔符的字符串,你可能需要先使用正则表达式或字符串替换方法将其转换为纯数字字符串,然后再进行数值操作。
2 个回答

有几个点需要明确下:小数点第2位等于5怎么办;向上取整是向上多少位,比如5.183是取5.19还是5.20,如果是第一种,用下面第一个函数,第二种用下面第二个函数。函数结果有保留一位小数的情况,看你需求再加上补0的操作

function NumFixed(num, digits) {
    let exponent = 10 **  digits;
    let d = num * exponent | 0
    return (d + (String(d).slice(-1) >= 5 ? 1 : 0)) / exponent
}

// 小数点第二位,大于等于5保留1位小数,否则保留2为小数
function NumFixed(num, digits) {
    return num.toFixed(digits - (String(num * 10 **  digits | 0).slice(-1) >= 5 ? 1 : 0))
}

方法二完善,结尾补0

function NumFixed(num, digits) {
    let isCeil = String(num * 10 **  digits | 0).slice(-1) >= 5
    return (isCeil ? Number(num.toFixed(digits - 1)) : num).toFixed(digits)
}

我重新写了代码,你可以测试一下,看这个有没有问题,我试了好像没啥问题:

function preciseRound(number) {
    const factor = 100; // 定义因子,用于将小数点后两位转化为整数进行处理

    // 先将数字扩大100倍,取整后还原
    let rounded = Math.round(number * factor) / factor;

    // 获取小数点后第三位
    let decimal = (number * factor * 10) % 10;

    // 决定是向上取整还是向下取整
    let finalNumber = (decimal >= 5) ? 
        Math.ceil(number * factor) / factor : 
        Math.floor(number * factor) / factor;

    return finalNumber; // 直接返回数值,不转换为字符串
}

// 测试示例1
let num1 = 5512.1913;
console.log(preciseRound(num1)); // 期望输出: 5512.20

// 测试示例2
let num2 = 173.544;
console.log(preciseRound(num2)); // 期望输出: 173.54

// 边界测试示例1
let num3 = 1000.999;
console.log(preciseRound(num3)); // 期望输出: 1001.00

// 边界测试示例2
let num4 = 500.0004;
console.log(preciseRound(num4)); // 期望输出: 500.00

// 边界测试示例3
let num5 = 5.55;
console.log(preciseRound(num5)); // 期望输出: 5.55

// 边界测试示例4
let num6 = 2;
console.log(preciseRound(num6)); // 期望输出: 2.00

逻辑说明

  1. 定义因子:使用一个因子 factor 为 100,将数字的小数点后两位转化为整数进行处理。
  2. 初步四舍五入:使用 Math.round(number * factor) / factor 对数字进行初步的四舍五入处理,确保初始精度。
  3. 判断最后一位并取整:通过 (number * factor * 10) % 10 获取小数点后第3位的值,如果该值大于等于 5,使用 Math.ceil;否则使用 Math.floor
  4. 返回结果:直接返回处理后的数值。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏