有什么不明白的地方,扫描右方二维码加我微信交流。
       

最近项目中有对数字添加逗号分隔符的需求,总结出三种方法。由于在短时间内需要对大量数据进行操作,所以做了一下效率分析。

方法有四种,效率从高到低依次:

  1. 从数字的末尾开始向前取三位(每次对1000取余数),不够三位的补0,剩下的数字用前面的规则递归,最终将字符串连接。
  2. 把数字转化成字符串,然后从后往前每三位添加一个逗号,输出最后的字符串。
  3. 使用正则表达式。
  4. 使用系统自带的num.toLocaleString()方法。

方法一:

let func1 = function (num) {
	if (num >= 1000) {
        let num1 = Math.floor(num / 1000);
        let num2 = num % 1000;
        num2 += '';
        let numLength = num2.length;
        if (num2.length < 3) {
            for (let i = 0; i < 3 - numLength; ++ i) {
                num2 = '0' + num2;
            }
        }
        return func1(num1) + ',' + num2;
    } else {
        return num;
    }
}

此算法每次将数字分割成两部分,百位以下(包含百位)和千位以上(包含千位),对百位以下的三位数进行格式化处理,不足三位的用0补齐。对千位以上的数再次进行分割,也就是递归,直到分割到要处理的数字不足三位,最后使用逗号连接输出。

方法二:

let func2 = function (num) {
	num = (num || 0).toString();
    let result = '';
    let str = ',';
    while (num.length > 3) {
        result = str + num.slice(-3) + result;
        num = num.slice(0, num.length - 3);
    }
    if (num) { result = num + result; }
    return result;
}

此算法将数字转化成字符串,然后把字符串当成数组来处理,每次拿数组末尾的三个元素,加逗号,直到拿不出三个元素来,输出结果。

方法三:

let func3 = function (num) {
	return num.toString().replace(/(?=(\B)(\d{3})+$)/g, ",");
}

使用正则表达式看起来高大上,然而效率却差的一批,有点令人失望了。

更多关于正则表达式的知识,请点击学习

方法四:

let func4 = function (num) {
    return num.toLocaleString();
}

采用系统自带方法,想不到是效率最低的,而且此方法还有兼容性问题。当然,这个方法还有更加丰富的用法,读者可以自行了解一下,点解了解

效率分析:

对以上四个方法进行测试,从0到1亿的数字进行格式化,通过对比运行时间长短来验证效率。

for (let i = 0; i < 100000000; ++ i) {
	// func1(i);//6.6s
	// func2(i);//16.9s
	// func3(i);//35.3s
    // func4(i);//59.7s
}

说一下以下方法的学习经历。第一个方法是在项目中第一次就写出来的,上线之后游戏的运行效率有所下降,查找原因的过程中怀疑过此算法的效率问题。向同事学习了解到第二种方法。自行google到第三四种方法。本来对正则和自带方法充满了希冀,以为是最佳解决方案。但通过测试对比得出,第一次的方法是效率最高的,游戏的运行效率下降另有原因。

 

2020.9.15更新

有同学评论说处理浮点数时,方法三要比方法一效率高一些,于是我对方法三和一进行了以下改良进行测试:

方法一改良:

把源数据分成两部分,千位以上和千位以下,千位以下做补0处理,千位以上每3位一个逗号,最后拼接两部分字符串,代码如下:

let func1 = function (num) {
    var num1 = Math.floor(num / 1000);
    var num2 = num % 1000;

    if (num2 < 100){
        if (num2 < 10){
            num2 = "0" + num2;
        }
        num2 = "0" + num2;
    }

    if (num1 > 0){
        return func11(num1) + "," + num2;
    }
    return num2;
}

let func11 = function (num) {
    if (num >= 1000) {
        let num1 = Math.floor(num / 1000);
        let num2 = num % 1000;
        num2 += '';
        let numLength = num2.length;
        if (num2.length < 3) {
            for (let i = 0; i < 3 - numLength; ++ i) {
                num2 = '0' + num2;
            }
        }
        return func11(num1) + ',' + num2;
    } else {
        return num;
    }
}

 

方法三改良:

添加处理浮点数的正则表达式,代码如下:

let func3 = function (num) {
    num = num.toString();
    //浮点数
    if (num.indexOf("." == -1)){
        return num.replace(/(\d)(?=(\d{3})+\.)/g, '$&,');;  
    } 

    //整数
    return num.replace(/(?=(\B)(\d{3})+$)/g, ",");
}

 

测试结果如下:

for (let i = 0; i < 100000000; ++ i) {
    // i += 0.0001;
    // func1(i);//31.5s
    // func3(i);//116.5s
}

依然是方法一效率高。

2 对 “javascript数字添加逗号分隔符”的想法;

  1. 在下测试后发现第一种方法和第三种方法各有千秋,第一种方法如果出现浮点数的话,小数部分会出现偏差;第三种方法无法识别小数。
    通过改良后,对整型数字的处理第一种方法无疑是最快的,但如果是浮点型的话,第一种方法稍逊于第三种方法。

    1. 我也进行了测试,博客已更新,依然是方法一最快。可能是我们的改良方法不一样,如果还有什么疑问,欢迎加我微信讨论,扫描右上二维码加我。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注