摘要:然后我立馬丟了一個(gè)以前我寫的一個(gè)轉(zhuǎn)中文數(shù)字的過濾器代碼小寫數(shù)字轉(zhuǎn)換成大寫只處理到零一二三四五六七八九十百千萬億十十零接下來就有人回應(yīng)你這種寫法要命了才就這么長(zhǎng),如果呢然后我以項(xiàng)目當(dāng)時(shí)需求就只到位為由回應(yīng)。
有一次在上海前端交流群看見有人在群里發(fā)了一個(gè)求助信息:
請(qǐng)用JavaScript語言編寫一個(gè)函數(shù),要求入口參數(shù)為數(shù)字, 取值范圍是一位數(shù)整數(shù),返回值是字符串,該函數(shù)的功能為:返回該數(shù)字對(duì)應(yīng)的漢字,例如:輸入數(shù)字6,返回漢字“六”;輸入數(shù)字9,返回漢字“九”。
然后我立馬丟了一個(gè)以前我寫的一個(gè)轉(zhuǎn)中文數(shù)字的angular過濾器代碼
//- 小寫數(shù)字轉(zhuǎn)換成大寫, 只處理到[0 ~ 99] function numberConvertToUppercase() { return function(num) { num = Number(num); var upperCaseNumber = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "百", "千", "萬", "億"]; var length = String(num).length; if (length == 1) { return upperCaseNumber[num]; } else if (length == 2) { if (num == 10) { return upperCaseNumber[num]; } else if (num > 10 && num < 20) { return "十" + upperCaseNumber[String(num).charAt(1)]; } else { return upperCaseNumber[String(num).charAt(0)] + "十" + upperCaseNumber[String(num).charAt(1)].replace("零", ""); } } } }
接下來就有人回應(yīng):
wolf 你這種寫法要命了
才99 就這么長(zhǎng), 如果 99999呢
然后我以項(xiàng)目當(dāng)時(shí)需求就只到2位為由回應(yīng)。后來自己去嘗試寫一個(gè)完整的轉(zhuǎn)換方法。嘗試了很多次總是有一些細(xì)節(jié)沒有考慮全。
經(jīng)過多次測(cè)試后下面給出一個(gè)我最終寫出的一個(gè)完整版本,供參考:
/** * 阿拉伯?dāng)?shù)字轉(zhuǎn)中文數(shù)字, * 如果傳入數(shù)字時(shí)則最多處理到21位,超過21位js會(huì)自動(dòng)將數(shù)字表示成科學(xué)計(jì)數(shù)法,導(dǎo)致精度丟失和處理出錯(cuò) * 傳入數(shù)字字符串則沒有限制 * @param {number|string} digit */ function toZhDigit(digit) { digit = typeof digit === "number" ? String(digit) : digit; const zh = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]; const unit = ["千", "百", "十", ""]; const quot = ["萬", "億", "兆", "京", "垓", "秭", "穰", "溝", "澗", "正", "載", "極", "恒河沙", "阿僧祗", "那由他", "不可思議", "無量", "大數(shù)"]; let breakLen = Math.ceil(digit.length / 4); let notBreakSegment = digit.length % 4 || 4; let segment; let zeroFlag = [], allZeroFlag = []; let result = ""; while (breakLen > 0) { if (!result) { // 第一次執(zhí)行 segment = digit.slice(0, notBreakSegment); let segmentLen = segment.length; for (let i = 0; i < segmentLen; i++) { if (segment[i] != 0) { if (zeroFlag.length > 0) { result += "零" + zh[segment[i]] + unit[4 - segmentLen + i]; // 判斷是否需要加上 quot 單位 if (i === segmentLen - 1 && breakLen > 1) { result += quot[breakLen - 2]; } zeroFlag.length = 0; } else { result += zh[segment[i]] + unit[4 - segmentLen + i]; if (i === segmentLen - 1 && breakLen > 1) { result += quot[breakLen - 2]; } } } else { // 處理為 0 的情形 if (segmentLen == 1) { result += zh[segment[i]]; break; } zeroFlag.push(segment[i]); continue; } } } else { segment = digit.slice(notBreakSegment, notBreakSegment + 4); notBreakSegment += 4; for (let j = 0; j < segment.length; j++) { if (segment[j] != 0) { if (zeroFlag.length > 0) { // 第一次執(zhí)行zeroFlag長(zhǎng)度不為0,說明上一個(gè)分區(qū)最后有0待處理 if (j === 0) { result += quot[breakLen - 1] + zh[segment[j]] + unit[j]; } else { result += "零" + zh[segment[j]] + unit[j]; } zeroFlag.length = 0; } else { result += zh[segment[j]] + unit[j]; } // 判斷是否需要加上 quot 單位 if (j === segment.length - 1 && breakLen > 1) { result += quot[breakLen - 2]; } } else { // 第一次執(zhí)行如果zeroFlag長(zhǎng)度不為0, 且上一劃分不全為0 if (j === 0 && zeroFlag.length > 0 && allZeroFlag.length === 0) { result += quot[breakLen - 1]; zeroFlag.length = 0; zeroFlag.push(segment[j]); } else if (allZeroFlag.length > 0) { // 執(zhí)行到最后 if (breakLen == 1) { result += ""; } else { zeroFlag.length = 0; } } else { zeroFlag.push(segment[j]); } if (j === segment.length - 1 && zeroFlag.length === 4 && breakLen !== 1) { // 如果執(zhí)行到末尾 if (breakLen === 1) { allZeroFlag.length = 0; zeroFlag.length = 0; result += quot[breakLen - 1]; } else { allZeroFlag.push(segment[j]); } } continue; } } --breakLen; } return result; }
關(guān)于中文計(jì)數(shù)單位可以網(wǎng)上自行搜索。
上面的代碼大體思路是:
從左至右,先把數(shù)字按萬分位分組,每組加上對(duì)應(yīng)的單位(萬,億, ...), 然后每個(gè)分組進(jìn)行迭代。breakLen表示能夠分成多少個(gè)分組,notBreakSegment表示當(dāng)前已處理過的分組長(zhǎng)度。while循環(huán)中有一個(gè)if判斷,如果不存在result,則說明是第一次處理,那么在處理上是有些不同的。首先,在segment的賦值上,第一次是從0開始,取notBreakSegment的長(zhǎng)度,后面每迭代一次notBreakSegment都要在上一個(gè)值上加4;其次,第一次處理不用判斷上一個(gè)分組是否全為0的情形,這里zeroFlag表示每一個(gè)分組內(nèi)存在0的個(gè)數(shù),allZeroFalg表示當(dāng)前分組前面出現(xiàn)的全為0的分組的個(gè)數(shù)。此外,在第一次執(zhí)行時(shí),還處理了只傳入為0的情形。
每次處理segment[i]時(shí),都要先判斷當(dāng)前值是否為0,為0時(shí)則直接記錄到zeroFlag,然后進(jìn)入下一次迭代,如果不為0,首先得判斷上一個(gè)數(shù)字是否為0, 然后還得根據(jù)上一個(gè)0是否位于上一個(gè)分組的末位,來添加quot,最后還需要清空標(biāo)志位。如果當(dāng)前分組全為0,則標(biāo)記allZeroFlag,所以在下一個(gè)分組處理時(shí),還需要判斷上一個(gè)分組是否全為0
。
更多細(xì)節(jié)直接看代碼,這里就不多作解釋了。
接下來是中文轉(zhuǎn)阿拉伯?dāng)?shù)字,這個(gè)處理起來比較簡(jiǎn)單,這里采用從右至左的方式對(duì)每一位進(jìn)行迭代,直接上代碼:
function zhDigitToArabic(digit) { const zh = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]; const unit = ["千", "百", "十"]; const quot = ["萬", "億", "兆", "京", "垓", "秭", "穰", "溝", "澗", "正", "載", "極", "恒河沙", "阿僧祗", "那由他", "不可思議", "無量", "大數(shù)"]; let result = 0, quotFlag; for (let i = digit.length - 1; i >= 0; i--) { if (zh.indexOf(digit[i]) > -1) { // 數(shù)字 if (quotFlag) { result += quotFlag * getNumber(digit[i]); } else { result += getNumber(digit[i]); } } else if (unit.indexOf(digit[i]) > -1) { // 十分位 if (quotFlag) { result += quotFlag * getUnit(digit[i]) * getNumber(digit[i - 1]); } else { result += getUnit(digit[i]) * getNumber(digit[i - 1]); } --i; } else if (quot.indexOf(digit[i]) > -1) { // 萬分位 if (unit.indexOf(digit[i - 1]) > -1) { if (getNumber(digit[i - 1])) { result += getQuot(digit[i]) * getNumber(digit[i - 1]); } else { result += getQuot(digit[i]) * getUnit(digit[i - 1]) * getNumber(digit[i - 2]); quotFlag = getQuot(digit[i]); --i; } } else { result += getQuot(digit[i]) * getNumber(digit[i - 1]); quotFlag = getQuot(digit[i]); } --i; } } return result; // 返回中文大寫數(shù)字對(duì)應(yīng)的阿拉伯?dāng)?shù)字 function getNumber(num) { for (let i = 0; i < zh.length; i++) { if (zh[i] == num) { return i; } } } // 取單位 function getUnit(num) { for (let i = unit.length; i > 0; i--) { if (num == unit[i - 1]) { return Math.pow(10, 4 - i); } } } // 取分段 function getQuot(q) { for (var i = 0; i < quot.length; i++) { if (q == quot[i]) { return Math.pow(10, (i + 1) * 4); } } } }
說明:代碼僅供參考,作者只寫了一些特殊數(shù)字和隨機(jī)數(shù)字進(jìn)行測(cè)試,不能保證百分百準(zhǔn)確,如果有問題請(qǐng)留言反饋。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/88211.html
摘要:除法大前端數(shù)字類型與字符串除法運(yùn)算,同樣會(huì)先將字符串轉(zhuǎn)為數(shù)字類型再做算術(shù)運(yùn)算,同樣與布爾類型做算術(shù)運(yùn)算,也是先把布爾類型轉(zhuǎn)換為數(shù)字類型再做算術(shù)運(yùn)算,但是遇到字符串里包含有英文或者中文將會(huì)得到結(jié)果。 算數(shù)運(yùn)算符 包含+、-、*、/、%,下面通過代碼示例來給大家進(jìn)行演示一下;加法: var num=100; var str1=大前端; var str2=300; var boo=true;...
摘要:來源編程精解中文第三版翻譯項(xiàng)目原文譯者飛龍協(xié)議自豪地采用谷歌翻譯部分參考了編程精解第版在機(jī)器的表面之下,程序在運(yùn)轉(zhuǎn)。本章將會(huì)介紹程序當(dāng)中的基本元素,包括簡(jiǎn)單的值類型以及值運(yùn)算符。示例中的乘法運(yùn)算符優(yōu)先級(jí)高于加法。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Values, Types, and Operators 譯者:飛龍 協(xié)議:CC BY-NC...
摘要:解釋一行,執(zhí)行一行這也意味著你可以使用同一個(gè)變量保存不同類型的數(shù)據(jù)二數(shù)據(jù)類型最新的標(biāo)準(zhǔn)定義了種數(shù)據(jù)類型種原型數(shù)據(jù)類型布爾值,和一個(gè)表明值的特殊關(guān)鍵字。我們稱這些類型的值為原始值四布爾值布爾值數(shù)據(jù)類型只能有兩個(gè)值,它們是文本和。 一、動(dòng)態(tài)類型 JavaScript 是一種弱類型或者說動(dòng)態(tài)語言。這意味著你不用提前聲明變量的類型,在程序運(yùn)行過程中,類型會(huì)被自動(dòng)確定。(解釋一行,執(zhí)行一行)這也...
摘要:總結(jié)通過使用和,我們能夠在數(shù)據(jù)和二進(jìn)制數(shù)據(jù)中進(jìn)行互相轉(zhuǎn)換。下一篇系列相關(guān)的博客,將會(huì)介紹如何通過來向后端傳遞二進(jìn)制數(shù)據(jù),以及如何處理通過收到的二進(jìn)制數(shù)據(jù)。 概述 上一篇博客我們說到了如何進(jìn)行數(shù)字類型(如Short、Int、Long類型)如何在JavaScript中進(jìn)行二進(jìn)制轉(zhuǎn)換,如果感興趣的可以可以閱讀本系列第二篇博客——WebSocket系列之JavaScript中數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為...
摘要:雖然會(huì)輸出,但是這只是存在的一個(gè)悠久。在的最初版本中使用的是位系統(tǒng),為了性能考慮使用低位存儲(chǔ)變量的類型信息,開頭代表是對(duì)象,然而表示為全零,所以將它錯(cuò)誤的判斷為。 參考來源: JavaScript高級(jí)程序設(shè)計(jì):?book.douban.com/subject/105… 千古壹號(hào):?github.com/qianguyihao… 小冊(cè)前端面試之道:?juejin.im/book/5bdc71…...
閱讀 2741·2023-04-26 02:02
閱讀 2621·2023-04-25 20:38
閱讀 4162·2021-09-26 09:47
閱讀 3150·2021-09-10 10:50
閱讀 3813·2021-09-07 09:58
閱讀 3359·2019-08-30 15:54
閱讀 2722·2019-08-30 15:54
閱讀 1941·2019-08-29 17:03