@xuyun19840618 さんの「漢数字とアラビア数字の相互変換」を拝見し、私なりの実装をコメントに書かせていただきました。
どうせなら、漢数字のまま計算できたら面白いかな? と思ってクラスにしてみました。
intクラスのサブクラスにして演算できるようにしています。
intのインスタンスはimmutable(不変)なので、値は __new__
メソッドで与えなければいけません。
演算結果は再びKanjiIntのインスタンスにしないと漢字表示にならないので、演算メソッドをオーバーライドしてKanjiIntにしています。いちいちメソッド定義するのは大変なので、forループで単項演算子と二項演算子のメソッドをオーバーライドしてます。
class KanjiInt(int):
def __new__(cls, value=0):
arabic = kanji_to_int(value)
if isinstance(arabic, int):
value = arabic
return int.__new__(cls, value)
def __str__(self):
return int_to_kanji(self)
def __repr__(self):
return 'KanjiInt(%s)' % repr(str(self))
_unary = ('abs', 'inv', 'invert', 'neg', 'pos')
_binary = ('add', 'sub', 'mul', 'floordiv', 'mod', 'pow',
'and', 'or', 'xor', 'lshift', 'rshift')
for method in _unary:
exec(f'KanjiInt.__{method}__ = lambda self: KanjiInt(int.__{method}__(self))')
for method in _binary:
exec(f'KanjiInt.__{method}__ = lambda self, value: KanjiInt(int.__{method}__(self, value))')
unitlong = '恒河沙', '阿僧祇', '那由他', '不可思議', '無量大数'
unit4 = ('',) + tuple('万億兆京垓秭穣溝澗正載極') + unitlong
unit1 = ('',) + tuple('十百千')
digits = tuple('〇一二三四五六七八九')
arabic4 = {unit[:1]: 10000**i for i, unit in enumerate(unit4)}
arabic1 = {unit: 10**i for i, unit in enumerate(unit1)}
arabics = {digit: i for i, digit in enumerate(digits)}
def int_to_kanji(arabic):
arabic = int(arabic)
if arabic == 0:
return digits[0]
sign = '-' if arabic < 0 else ''
arabic = abs(arabic)
def convert():
for column, digit in enumerate(map(int, str(arabic)[::-1])):
if column % 4 == 0 and (arabic // (10 ** column)) % 10000 != 0:
yield unit4[column // 4]
if digit != 0:
yield unit1[column % 4]
if digit != 1 or column % 4 == 0: # 一千,一百,一十の 一 は除く
yield digits[digit]
return sign + ''.join(list(convert())[::-1])
def kanji_to_int(kanji):
if not isinstance(kanji, str):
return 'error'
for longname in unitlong:
kanji = kanji.replace(longname, longname[0])
a0 = a1 = a4 = 0
for j in kanji:
if j in arabics:
a0 = a0 * 10 + arabics[j]
elif j in arabic1:
a1 += (a0 or 1) * arabic1[j]
a0 = 0
elif j in arabic4:
a4 += (a0 + a1 or 1) * arabic4[j]
a0 = a1 = 0
else:
return 'error'
return a0 + a1 + a4
if __name__ == '__main__':
value = KanjiInt('五十六')
print("value =", value)
print('repr(value) =', repr(value))
print('str(value) =', str(value))
print('int(value) =', int(value))
print('abs(value) =', abs(value))
print('+value =', +value)
print('-value =', -value)
print('~value =', ~value)
print('value + 3 =', value + 3)
print('3 + value =', 3 + value)
print('value - 3 =', value - 3)
print('value * 3 =', value * 3)
print('value / 3 =', value / 3)
print('value // 3 =', value // 3)
print('value % 3 =', value % 3)
print('value ** 3 =', value ** 3)
print('value & 3 =', value & 3)
print('value | 3 =', value | 3)
print('value ^ 3 =', value ^ 3)
print('value << 3 =', value << 3)
print('value >> 3 =', value >> 3)
実行結果
value = 五十六
repr(value) = KanjiInt('五十六')
str(value) = 五十六
int(value) = 56
abs(value) = 五十六
+value = 五十六
-value = -五十六
~value = -五十七
value + 3 = 五十九
3 + value = 59
value - 3 = 五十三
value * 3 = 百六十八
value / 3 = 18.666666666666668
value // 3 = 十八
value % 3 = 二
value ** 3 = 十七万五千六百十六
value & 3 = 〇
value | 3 = 五十九
value ^ 3 = 五十九
value << 3 = 四百四十八
value >> 3 = 七