javascript数字添加逗号分隔符
有什么不明白的地方,扫描右方二维码加我微信交流。
最近项目中有对数字添加逗号分隔符的需求,总结出三种方法。由于在短时间内需要对大量数据进行操作,所以做了一下效率分析。
方法有四种,效率从高到低依次:
- 从数字的末尾开始向前取三位(每次对1000取余数),不够三位的补0,剩下的数字用前面的规则递归,最终将字符串连接。
- 把数字转化成字符串,然后从后往前每三位添加一个逗号,输出最后的字符串。
- 使用正则表达式。
- 使用系统自带的
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 }
依然是方法一效率高。
在下测试后发现第一种方法和第三种方法各有千秋,第一种方法如果出现浮点数的话,小数部分会出现偏差;第三种方法无法识别小数。
通过改良后,对整型数字的处理第一种方法无疑是最快的,但如果是浮点型的话,第一种方法稍逊于第三种方法。
我也进行了测试,博客已更新,依然是方法一最快。可能是我们的改良方法不一样,如果还有什么疑问,欢迎加我微信讨论,扫描右上二维码加我。