阿拉伯-漢字-數字轉換

說明

本文實現了一個從阿拉伯數字到中文數字,以及從中文數字到阿拉伯數字的轉換算法。
同時用Vuejs和Angularjs同時實現了一遍,對比了一下這兩個框架的優劣。在本例中,Vuejs的方便靈活性完勝Angularjs。html

源代碼在這裏jquery

阿拉伯數字轉中文

給定一個阿拉伯數字,把它轉變爲漢語表示的數字。git

算法

根據中文的計數方法,能夠把阿拉伯數字按4個一組分紅若干section,每一個section從低到高的單位分別爲 「」,「萬」,「億」,「萬億」。angularjs

每一個section內的轉換方法是同樣的,好比1234,就是"一千二百三十四",加上對應的單位,如「萬」,就是「一千二百三十四萬」。可是在其中又有些細節須要注意:github

  • 結尾的零都忽略,如1200,就是一千二百算法

  • 中間的零,只須要用一個零表示,如1004,是一千零四app

  • 若是整個section都是0,所有忽略框架

  • 若是section在10到19之間,則十位能夠省略一;不然,十位上的「一」都不能省。如12就是「十二」,312就是「三百一十二」函數

中文轉阿拉伯數字

給定一箇中文數字,如「一千二百三十四萬」,把它們轉換成阿拉伯數字ui

算法

跟上面相似,以「萬」,「億」,「萬億」爲分割位,先把中文分紅若干section,每一個section的轉換方法同樣,而後section數值乘以相應的權重,如section爲「萬」就是乘以10000,「億」是乘以100000000,最低位的section,權重就是1。
將每一個section的結果累加就是最終結果。

每一個section最多8個漢字,都是以「數字+單位」的形式成對出現。將數字*單位的結果累加起來就是最終結果。單位從低到高就是1,10, 100, 1000。

須要注意的細節有:

  • 「零」忽略便可

  • 若是第一位是「十」,則數字默認爲一。

實現細節

分別經過Vuejs和angularjs實現了一遍,正好能夠對比一下兩者的不一樣。大部分代碼兩者都差很少。

可是爲了方便閱讀,我對阿拉伯數字採用了千分位分隔,當用戶在輸入框中輸入完成按下回車後,輸入框內的阿拉伯數字自動用逗號分隔。差別注意出如今這個實現方法上。

Vuejs實現

// html視圖:
<input type="text" v-model="ArabNum|thousandth">

// js邏輯:
var app = new Vue({
    el: "#app",
    data: {
        ArabNum: 0,
        ChineseNum: "",
        //ChineseSymbole: ["零", "壹", "貳", "叄", "肆", "伍", "陸", "柒", "捌", "玖"],
        ChineseSymbole: ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"],
        ChineseSection: ["", "萬", "億", "萬億"],
        //ChineseUnit: ["", "拾", "佰", "仟"],
        ChineseUnit: ["", "十", "百", "千"],
        ChineseUnitArab: {
            "零": 0,
            "一": 1,
            "二": 2,
            "三": 3,
            "四": 4,
            "五": 5,
            "六": 6,
            "七": 7,
            "八": 8,
            "九": 9,
            "十": 10,
            "百": 100,
            "千": 1000,
            "萬": 10000,
            "億": 100000000,
            "萬億": 1000000000000,
        }
    },
    // 區別主要在這裏:
    filters: {
        thousandth: {
            read: function(v) {
                var str = "";
                while (v > 0) {
                    var left = "" + (v % 1000);
                    v = Math.floor(v / 1000);
                    if (v > 0) {
                        while (left.length < 3) {
                            left = "0" + left;
                        }
                    }
                    if (str == "") {
                        str = left;
                    } else {
                        str = left + "," + str;
                    }
                }
                return str;
            },
            write: function(v) {
                return parseInt(v.replace(/,/g, ""));
            },
        },
    },
    methods: {
        Arab2Chn: function(v) { ... },
        Arab2Chn_section: function(v) { ... },
        Chinese2Arab: function(str) { ... },
        Chinese2Arab_section: function(str) { ... },
    },
    computed: { ... },
})

Vuejs方便的地方在於,filter能夠用在v-model中,只要分別設計read和write函數便可實現雙向綁定。read用於model到view的轉換,write用於view到model的轉換。

Angularjs實現

相比於Vuejs,若是在ng-model中直接使用filter,會報錯:

<input type="text" ng-model="ArabNum|thousandth" >
// error:
Expression 'ArabNum|thousandth' is non-assignable

爲了實現和Vuejs相似的邏輯,我首先google了一下,發現只能經過directive實現:

app.directive("thousandth", function() {
    return {
        require: "ngModel",
        link: function(scope, elm, attr, ngModel) {
            function thousandth(v) {
                var str = "",
                    v = "" + v;
                v = v.replace(/,/g, "");
                while (v > 0) {
                    var left = "" + (v % 1000);
                    v = Math.floor(v / 1000);
                    if (v > 0) {
                        while (left.length < 3) {
                            left = "0" + left;
                        }
                    }
                    if (str == "") {
                        str = left;
                    } else {
                        str = left + "," + str;
                    }
                }
                return str;
            }

            elm.on("blur", function(v) {
                elm.val(thousandth(ngModel.$modelValue));
            });
            // model -> view
            ngModel.$formatters.push(function(data) {
                return thousandth(data)
            })
            // view -> model
            ngModel.$parsers.push(function(v) {
                v = "" + v;
                return parseInt(v.replace(/,/g, ""));
            });
        }
    }
})

能夠看到,首先ng的語法要麻煩不少。並且$formatters只有在內部的model被改變時,纔會對view生效。好比input改變時,$parsers先調用(V-->M),返回值直接給了ngModel,可是$formatters不會調用,即M-->V不會被調用,不然 M修改V,V又修改M,就是死循環了。

只有你經過程序修改了ArabNum後,$formatters纔會調用(M-->V)。因此,必須經過jquery的方式,在blur函數中,對element的value進行直接修改,才能實現上述Vue的效果。

總結

只要仔細一點,耐心一點,兩個數字表示方式的轉換仍是比較容易實現的。

經過對比Vue和angular能夠看到,Vue確實比Ng要方便些。這只是其中的一個方面。

相關文章
相關標籤/搜索