Help us understand the problem. What is going on with this article?

漢数字クラスで演算処理

@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 = 七
shiracamus
元、低レイヤーエンジニア。 現、サイバーセキュリティ研究者。 使用言語は、C, Lisp, Java, Python, C#, JavaScript/Node.js。 経験アセンブリ言語は Z80, 6502, 6809, 68000, SPARC, PowerPC, ARM, x86/x64。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away