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)