昨天做一個頁面有一個需求,需要把伺服器取過來的數字(也有可能是數字字符串),將小數點前的數字每隔三位添加一個逗號(前面數是一個四位數的值)。比如取到的值是123456,要將其轉換成123,456。搜索了一下,這叫數字分們符號。
為了方便閱讀小數點前後的數字可以被分組,由於國際上語言裡最常見的數字讀法是千位分位,寫法的分組也是在千位數上。 如果當地習俗是用句點作小數點,千位的分號一般是逗號或空格。如果習俗裡小數點是逗號,千位分號一般是句點或空格。由於可能產生歧義,國際標準建議、國際度量衡局更是要求用空格而不要用逗號或點。
不同國家有不同的標準要求,我們看看我國的標準:
為便於閱讀,四位以上的整數或小數,可採用以下兩種方式分節:
千分撇: 整數部分每三位一組,以,分節。小數部分不分節。四位以內的整數可以不分節。如:624,000、 92,300,000、19,351,235.235767,1256
千分空: 從小數點起,向左和向右每三位數字一組,組間空四分之一個漢字,即二分之一個阿拉伯數字的位置。四位以內的整數可以不加千分空。如:55 235、 367.346、 23 98 235、 358.238、 368
可見,中國正式場合的數字用法並非是以萬位數為一組來分節的。諸如123,4567.89的表示法是錯誤的。
JavaScript如何處理數字分位符在這樣的一個實際需求當中,取到的值不外呼是兩種,其一它就是一個數字類型(整型123456或者浮點型12345.09),其二是一個數字字符串,比如"123456"。那回到主題上,現在需要將這樣的數字或字符串做處理。
需要創建一個函數,比如addCommas(),並且給這個函數傳遞一個參數val。需要注意的是,這個val值有可能是數字類型,也有可能是字符類型。
不管獲取的val是什麼類型,首先通過toString()方法,將其轉換成字符串
由於取到的val值有可能是一個浮點數,而我們是需要給小數點前面的整數部分添加分位符號,;在JavaScript中可以通過split(".")將這個val轉換成一個數組aIntNmu。如果val值是一個整數,那麼得到的數組只有一個值,如果val是一個浮點數,那麼將會以小數點為分隔點,數整會有兩個元素值。我們要處理的將是aIntNum[0]。
通過正則replace()主法給aIntNum[0]做替換,這裡需要一個正則規則,比如/(\d+)(\d{3})/。正則這部分,對於我這樣的菜鳥而言還是很吃力的,不過這有個在線工具,可以檢測並解釋其函數。
如果你想讓JavaScript處理數字千分位更符合國家的標準,那麼在做數據替換時,還需要做一個條件判斷。比如說,只有當aIntNum[0].length大於或等於5的時候才添加分位符。
返回處理的數字
上面方法是通過數組來處理的,其實還可以直接通過字符串處理來解決。比如通過indexOf(".")對數字分隔,再配合for循環、charAt()和substr()等方法給數字添加分位符。接下來,我們一起看看代碼具體如何寫。
數組方案根據前面的介紹的,先用數組的方式來做:
function addCommas(val) { var aIntNum = val.toString().split('.'); var iIntPart = aIntNum[0]; var iFlootPart = aIntNum.length > 1 ? '.' + aIntNum[1] : ''; var rgx = /(\d+)(\d{3})/; if (iIntPart.length >= 5) { while (rgx.test(iIntPart)) { iIntPart = iIntPart.replace(rgx, '$1' + ',' + '$2'); } } return iIntPart + iFlootPart;}
上面的方法生不生效,難證一下就知道了:
addCommas(1234); addCommas(12345);addCommas(123456);addCommas(123456.4321);addCommas(123456.54321);addCommas(123456.654321);
上面的方法只能小數點前面的數做了處理,如果需要對小數點後面的也做相應的處理,就需要做一下處理:
function addCommas(val) { var aIntNum = val.toString().split('.'); var iIntPart = aIntNum[0]; var iFlootPart = aIntNum.length > 1 ? '.' + aIntNum[1] : ''; var rgx = /(\d+)(\d{3})/; if (iIntPart.length >= 5) { while (rgx.test(iIntPart)) { iIntPart = iIntPart.replace(rgx, '$1' + ',' + '$2'); } } if (iFlootPart && iFlootPart.length >= 5) { while (rgx.test(iFlootPart)) { iFlootPart = iFlootPart.replace(/(\d{3})/g, '$1 '); } } return iIntPart + iFlootPart;}
調試器裡繼續跑一下測試代碼:
addCommas(1234);addCommas(12345);addCommas(123456);addCommas(123456.4321);addCommas(123456.54321);addCommas(123456.654321);
效果是有,但感覺怪怪的。
上面的代碼可以精簡一下,變成這樣:
function addCommas(val) { var aIntNum = val.toString().split('.'); if (aIntNum[0].length >= 5) { aIntNum[0] = aIntNum[0].replace(/(\d)(?=(\d{3})+$)/g, '$1,'); } if (aIntNum[1] && aIntNum[1].length >= 5) { aIntNum[1] = aIntNum[1].replace(/(\d{3})/g, '$1 '); } return aIntNum.join('.');}
最後得到的效果就是一樣。
將上面代碼中的正則條件換換,也一樣可以達到相同的效果:
function addCommas(val) { var aIntNum = val.toString().split("."); if (aIntNum[0].length >= 5) { aIntNum[0] = aIntNum[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); } if (aIntNum[1] && aIntNum[1] >= 5) { aIntNum[1] = aIntNum[1] ? aIntNum[1].replace(/\B(?=(\d{3})+(?!\d))/g, " ") : " "; } return aIntNum.join(".");}
字符串方案前面也說了,除了將傳參轉換成數組去處理之外,還可以直接對傳參進行字符串的操作。下面收集了幾種方法,雖然達到需求,但還是略有不同之處。比如小數部分用的不是空格分開,而是使用逗號分開。另外一點,就是沒找到如何超過四位數才進行分隔處理。希望有高手能指點其中不足之處。
方法1function addCommas(val) { while (/(\d+)(\d{3})/.test(val.toString())) { val = val.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); } return val;}
方法2function addCommas(val) { var sIntNum = val.toString(), bIndex = sIntNum.indexOf('.'); return sIntNum.replace(/\d(?=(?:\d{3})+(?:\.|$))/g, function($0, i) { return bIndex < 0 || i < bIndex ? ($0 + ',') : $0; });}
方法3function addCommas(val) { return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");}
方法4function addCommas(val) { return (val + "").replace(/\b(\d+)((\.\d+)*)\b/g, function(a, b, c) { return (b.charAt(0) > 0 && !(c || ".").lastIndexOf(".") ? b.replace(/(\d)(?=(\d{3})+$)/g, "$1,") : b) + c; });}
總結上面整理了使用數組或者直接操作字符串的幾種方法,將一個數字或數字字符串,按照千分位的方式給其添加對應的分隔符,比如,或空格。雖然達到了一定的需求,但感覺裡面的還存在一定的問題,只是沒有找到問題所在。希望大嬸們指點其中不對之處,如果您有更好的方案,歡迎在下面的評論中與我們一起分享。
擴展閱讀文章涉及到圖片和代碼,如果展示不全給您帶來不好的閱讀體驗,歡迎點擊文章底部的 閱讀全文。如果您覺得小站的內容對您的工作或學習有所幫助,歡迎關注此公眾號。
W3cplus.com
————————————
記述前端那些事,引領web前沿
長按二維碼,關注W3cplus
▼