Arithmetic processing with Chinese numeral class

I read @ xuyun19840618's "Mutual conversion between Chinese numerals and Arabic numerals" and wrote my own implementation in the comments. Anyway, wouldn't it be interesting if we could calculate with Chinese numerals? I thought it was a class. It is made a subclass of int class so that it can be operated. The int instance is immutable, so the value must be given in the __new__ method. Since the operation result will not be displayed in Kanji unless it is made an instance of KanjiInt again, the operation method is overridden to KanjiInt. Since it is difficult to define the method one by one, the for loop overrides the methods of the unary operator and the binary operator.

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

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('KanjiInt.__{0}__ = lambda self: KanjiInt(int.__{0}__(self))'.format(method))

for method in _binary:
    exec('KanjiInt.__{0}__ = lambda self, value: KanjiInt(int.__{0}__(self, value))'.format(method))


unitlong = 'Tsunekawa Sha', 'A monk', 'Decillion and others', 'Mysterious', 'Immeasurable large number'
unit4 = ('',) + tuple('100 billion trillion kyoho') + unitlong
unit1 = ('',) + tuple('Ten thousand')
digits = tuple('〇 1 2 3 4 5 6 7 8 9')
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:  #One thousand,One hundred,Except for eleven
                    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('Fifty-six')
    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)

Execution result


value =Fifty-six
repr(value) = KanjiInt('Fifty-six')
str(value) =Fifty-six
int(value) = 56
abs(value) =Fifty-six
+value =Fifty-six
-value = -Fifty-six
~value = -Fifty-seven
value + 3 =Fifty-nine
3 + value = 59
value - 3 =Fifty-three
value * 3 =168
value / 3 = 18.666666666666668
value // 3 =XVIII
value % 3 =two
value ** 3 =175,616
value & 3 = 〇
value | 3 =Fifty-nine
value ^ 3 =Fifty-nine
value << 3 =448
value >> 3 =Seven

Recommended Posts

Arithmetic processing with Chinese numeral class
Page processing class
Image processing with MyHDL
Processing datasets with pandas (1)
Processing datasets with pandas (2)
Image processing with Python
Parallel processing with multiprocessing
Image Processing with PIL
Image processing with Python (Part 2)
100 Language Processing with Python Knock 2015
Parallel processing with local functions
"Apple processing" with OpenCV3 + Python3
Acoustic signal processing with Python
Parallel processing with Parallel of scikit-learn
Image processing with Python (Part 1)
Image processing with Python (Part 3)
Data processing tips with Pandas
[Python] Image processing with scikit-image
I tried natural number expression and arithmetic processing only with list processing