Traitement arithmétique dans la classe de nombres Kanji

J'ai lu "[Conversion mutuelle entre les nombres chinois et arabes] de @ xuyun19840618](http://qiita.com/xuyun19840618/items/a340f6dca5ef1cde7ac1)" et j'ai écrit ma propre implémentation dans les commentaires. Quoi qu'il en soit, ne serait-il pas intéressant de pouvoir calculer avec des nombres chinois? Je pensais que c'était une classe. Elle devient une sous-classe de la classe int afin qu'elle puisse être calculée. L'instance int est immuable, donc la valeur doit être donnée dans la méthode __new__. Étant donné que le résultat du calcul ne sera pas affiché dans Kanji à moins qu'il ne soit à nouveau créé une instance de KanjiInt, la méthode de calcul est remplacée par KanjiInt. Comme il est difficile de définir la méthode une par une, la boucle for remplace les méthodes de l'opérateur de terme unique et de l'opérateur binaire.

#!/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', 'Un moine', 'Nayu et autres', 'Mystérieux', 'Un grand nombre incommensurable'
unit4 = ('',) + tuple('100 milliards de milliards de Kyoho') + unitlong
unit1 = ('',) + tuple('Dix mille')
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:  #Mille,Cent,Sauf pour onze
                    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('Cinquante 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)

Résultat d'exécution


value =Cinquante six
repr(value) = KanjiInt('Cinquante six')
str(value) =Cinquante six
int(value) = 56
abs(value) =Cinquante six
+value =Cinquante six
-value = -Cinquante six
~value = -Cinquante sept
value + 3 =Cinquante neuf
3 + value = 59
value - 3 =Cinquante trois
value * 3 =168
value / 3 = 18.666666666666668
value // 3 =XVIII
value % 3 =deux
value ** 3 =175 616
value & 3 = 〇
value | 3 =Cinquante neuf
value ^ 3 =Cinquante neuf
value << 3 =448
value >> 3 =Sept

Recommended Posts

Traitement arithmétique dans la classe de nombres Kanji
Classe de traitement de page
Traitement d'image avec MyHDL
Traitement des ensembles de données avec des pandas (1)
Traitement des ensembles de données avec des pandas (2)
Traitement d'image avec Python
Traitement parallèle avec multitraitement
Traitement d'image avec PIL
Traitement d'image avec Python (partie 2)
100 coups de traitement du langage avec Python 2015
Traitement parallèle avec des fonctions locales
"Traitement Apple" avec OpenCV3 + Python3
Traitement du signal acoustique avec Python
Traitement parallèle avec Parallel de scikit-learn
Traitement d'image avec Python (partie 1)
Traitement d'image avec Python (3)
Conseils de traitement des données avec Pandas
[Python] Traitement d'image avec scicit-image
J'ai essayé l'expression des nombres naturels et le traitement arithmétique uniquement avec le traitement de liste