1
1

More than 5 years have passed since last update.

漢数字を算用数字に変換するコード

Last updated at Posted at 2018-06-13

python3系です。

仕事上で、漢数字を算用数字に変換する必要が生じたので、作ってみました。
ネット上で、同目的のプログラムもありましたが、自分に理解しにくい部分もあったので、自作してみようという試みです。

「二十万三百五十四」
というように、「十」なども入れる正式な記述だけに対応しています。

現時点ではバリデーションを付けていないため、変な文字列を投入しても一応数字がかえってしまいます。
正規表現を用いてバリデーションするのが王道でしょうか。

非エンジニアでずっと独学のため、他人に指導してもらった経験がありません。

  • 全体的な構成
  • アルゴリズムの適否
  • クラスの使い方
  • 変数の使い方
  • 変数名の付け方
  • より適切orスマートな書き方

などなど、お気づきの点について遠慮なくご意見をいただけると嬉しいです。

構成

二十八兆 一億 三百二十万 六千十八
という風に、4桁単位で区切ります。

そして、
二十八兆 億 三百二十万 六千十八
という風に、兆・億・万につく部分を1000以下の数字として捉え、数値に変換します(→_change_num_under1000)。
これに兆・億・万を数値として掛け算します。

たとえば二十八兆の場合は、
28 × 1000000000000
という風に計算します(→_change_num_over1000)。

最後に合計します。

コード

import re

class Kansuuji():
    def __init__(self,text=""):
        #不正な文字列に対するバリデーションがあるとよい。
        self.kan=text


    def _convert_single_KAN(self,one):
        chars={
        "一":1,
        "二":2,
        "三":3,
        "四":4,
        "五":5,
        "六":6,
        "七":7,
        "八":8,
        "九":9,
        "十":10,
        "百":100,
        "千":1000
        }
        return chars.get(one,1)    #十三など、一のつかないものに対応するため、getで1を返させている。

    def _change_num_under1000(self,text):

        C=self._convert_single_KAN
        val=0

        kans=(    
            ("千",1000),
            ("百",100),
            ("十",10)
        )    #処理順を保つためディクショナリは回避。

        for kan,num in kans:
            pat="([二三四五六七八九])?{}(.*)".format(kan)
            matobj=re.match(pat,text)
            if matobj:
                val+=C(matobj.group(1))*num
                text=matobj.group(2)

        if text:    #一の位を処理
            val +=C(text)

        return val

    def _change_num_over1000(self,text):
        val=0
        C2=self._change_num_under1000

        kans=(
            ("垓",100000000000000000000),
            ("京",10000000000000000),
            ("兆",1000000000000),
            ("億",100000000),
            ("万",10000)
        )    #現時点は垓までだが、ここに追加していけば全ての文字に対応可能。

        for kan,num in kans:
            pat="([一二三四五六七八九十百千]+){}(.*)".format(kan)
            matobj=re.match(pat,text)
            if matobj:
                val+=C2(matobj.group(1))*num
                text=matobj.group(2)

        return text,val


    def get_arabic(self,text=None):
        text=text if text else self.kan    #インスタンス作成時に引数を与えなくても動くようにしてみた。(こういうのはよくない??)
        text,val=self._change_num_over1000(text)
        return val+self._change_num_under1000(text)
1
1
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1