In het Japans zijn er twee manieren om getallen op te schrijven: met de voor ons gebruikelijke Arabische cijfers (1, 2, 3, …) of met de Chinese cijfers (一, 二, 三, …). De Arabische cijfers worden vaker gebruikt in horizontale regels en de Chinese cijfers worden meestal gebruikt in verticale regels.

De omzetting van Arabische naar Chinese cijfers volgt de Chinese traditie waarbij de cijfers vanaf rechts gegroepeerd worden per grootte van 10.000. Zo'n groep van vier cijfers wordt een myriade genoemd. Hieronder zie je bijvoorbeeld de omzetting van het getal 1234567890 naar Chinese cijfers (en de bijhorende uitspraak).

  1234567890
  0012 3456 7890
Arabisch 0 (×1000) 0 (×100) 1 (×10) 2 3 (×1000) 4 (×100) 5 (×10) 6 7 (×1000) 8 (×100) 9 (×10) 0
Chinees     三千 四百 五十 七千 八百 九十  
uitspraak     ni san-sen yon-hyaku go-jū roku nana-sen hachi-hyaku kyū-jū  

In eerste instantie wordt het getal 1234567890 opgesplitst in drie myriaden: 0012, 3456 en 7890. Daarbij hebben we de eerste myriade aangevuld met voorloopnullen, zodat elke myriade uit vier cijfers bestaat.

Voor de eenvoud leggen we eerst uit hoe een individuele myriade omgezet wordt naar Chinese cijfers of naar de bijhorende uitspraak. Beide omzettingen verlopen immers volledig analoog, behalve dat er extra scheidingstekens tussengevoegd worden in de schrijfwijze van de uitspraak. De vier cijfers van een myriade worden eerst elk afzonderlijk omgezet:

  1. Een cijfer 0 wordt niet omgezet. De andere cijfers worden omgezet volgens onderstaande tabel:

    Arabisch 0 1 2 3 4 5 6 7 8 9
    Chinees
    uitspraak zero ichi ni san yon go roku nana hachi kyū

    De voorstellingen van het cijfer 0 worden enkel gebruik als het volledige getal gelijk is aan nul (zie verder).

  2. De omzetting van de eerste drie cijfers (als die niet 0 zijn) wordt gevolgd door een aanduiding van de corresponderende macht van tien:

    macht ×10 ×100 ×1000
    Chinees
    uitspraak hyaku sen

    Als het cijfer gelijk is aan 1 dan bestaat de omzetting enkel uit de corresponderende macht van tien. Als de omzetting van een cijfer bestaat uit de twee delen, dan worden die qua Chinese cijfers gewoon achter elkaar geschreven en qua uitspraak van elkaar gescheiden door een koppelteken (-).

Daarna worden de omzettingen van de individuele cijfers van een myriade samengevoegd. Bij Chinese cijfers worden de omzettingen gewoon achter elkaar geschreven. Voor de uitspraak worden de omzettingen van elkaar gescheiden door een spatie.

Voor een getal in Arabische cijfers wordt de omzetting van elke myriade (behalve de meeste rechtse) door een aanduiding van de corresponderende macht van tien:

macht ×104 ×108 ×1012 ×1016 ×1020 ×1024 ×1028 ×1032 ×1036 ×1040 ×1044 ×1048
Chinees
uitspraak man oku chō kei gai jo kan sei sai goku

Zo wordt voor het getal 1234567890 de myriade 0012 omgezet naar 十二 (jū ni oku), de myriade 3456 naar 三千四百五十六 (san-sen yon-hyaku go-jū roku man) en de myriade 7890 naar 七千八百九十 (nana-sen hachi-hyaku kyū-jū). Bij Chinese cijfers worden de omzettingen gewoon achter elkaar geschreven. Voor de uitspraak worden de omzettingen van elkaar gescheiden door een komma en een spatie.

Een myriade 0000 wordt niet omgezet, behalve als het de meest rechtse is (zo krijgen we de voorstelling van het getal 0). Een myriade 0001 wordt wel omgezet, maar wordt in de schrijfwijze van de uitspraak gescheiden van zijn macht van tien (als die er is) door een koppelteken (-) in plaats van een spatie. Op die manier wordt 10000 omgezet naar 一万 (ichi-man) en dus niet "ichi man" of "man".

Opgave

Definieer een klasse Japans waarmee Japanse getallen kunnen voorgesteld worden. Bij het instantiëren van een Japans getal (Japans) moet de waarde van het getal doorgegeven worden als een natuurlijk getal $$i \in \mathbb{N}$$ (int) of als een stringvoorstelling $$s$$ (str) in Chinese cijfers. Als de gegeven waarde $$i$$ kleiner is dan nul, de gegeven stringvoorstelling $$s$$ niet bestaat uit Chinese cijfers, of als er een waarde met een ander gegevenstype wordt doorgegeven, dan moet een AssertionError opgeworpen worden met de boodschap ongeldig getal.

Zorg ervoor dat de klasse Japans de volgende statische methoden1 ondersteunt om de voorstellingen met Arabische en Chinese cijfers (en de bijhorende uitspraak) makkelijker naar elkaar te kunnen omzetten:

Als een Japans getal (Japans) wordt doorgegeven aan de ingebouwde functie int dan moet die de decimale waarde van het getal teruggeven. Als een Japans getal (Japans) wordt doorgegeven aan de ingebouwde functie str dan moet die de schrijfwijze van het getal in Chinese cijfers teruggeven. Analoog moet de ingebouwde functie repr een string (str) teruggeven waarvan je het formaat kan afleiden uit onderstaand voorbeeld. Een Japans getal (Japans) moet een eigenschap uitspraak hebben met als waarde de schrijfwijze van de Japanse uitspraak (str) van het getal.

Zorg ervoor dat de binaire operatoren voor de optelling (+), aftrekking (-), vermenigvuldiging (*), gehele deling (//), modulo (%) en machtsverheffing (**) telkens een nieuw Japans getal (Japans) opleveren als beide operandi Japanse getallen (Japans) zijn of als één van beide operandi een Japans getal (Japans) is en het ander een integer (int). Het resultaat van die bewerkingen moet dezelfde decimale waarde hebben als het resultaat dat deze operatoren opleveren voor twee integer operandi met dezelfde decimale waarde. Als de operator geen geldig Japans getal oplevert, dan moet een AssertionError opgeworpen worden met de boodschap ongeldig getal.

Als de zes vergelijkingsoperatoren (==, !=, <, <=, > en >=) worden toegepast op twee integers (int), dan levert dat telkens een Booleaanse waarde op. Zorg ervoor dat ze dezelfde Booleaanse waarde opleveren, als één of beide integers worden vervangen door een Japans getal (Japans) met dezelfde decimale waarde.

Voorbeeld

>>> Japans.splits_myriaden(1234567890)
['0012', '3456', '7890']
>>> Japans.myriade('0012')
'十二'
>>> Japans.myriade('3456')
'三千四百五十六'
>>> Japans.myriade('7890')
'七千八百九十'
>>> Japans.myriade('0012', uitspraak=True)
'jū ni'
>>> Japans.myriade('3456', uitspraak=True)
'san-sen yon-hyaku go-jū roku'
>>> Japans.myriade('7890', uitspraak=True)
'nana-sen hachi-hyaku kyū-jū'
>>> Japans.naarJapans(0)
'零'
>>> Japans.naarJapans(11)
'十一'
>>> Japans.naarJapans(17)
'十七'
>>> Japans.naarJapans(151)
'百五十一'
>>> Japans.naarJapans(302)
'三百二'
>>> Japans.naarJapans(469)
'四百六十九'
>>> Japans.naarJapans(2025)
'二千二十五'
>>> Japans.naarJapans(10000)
'一万'
>>> Japans.naarJapans(9836703)
'九百八十三万六千七百三'
>>> Japans.naarJapans(1234567890)
'十二億三千四百五十六万七千八百九十'
>>> Japans.naarJapans(2036521801)
'二十億三千六百五十二万千八百一'
>>> Japans.naarJapans(0, uitspraak=True)
'zero'
>>> Japans.naarJapans(11, uitspraak=True)
'jū ichi'
>>> Japans.naarJapans(17, uitspraak=True)
'jū nana'
>>> Japans.naarJapans(151, uitspraak=True)
'hyaku go-jū ichi'
>>> Japans.naarJapans(302, uitspraak=True)
'san-hyaku ni'
>>> Japans.naarJapans(469, uitspraak=True)
'yon-hyaku roku-jū kyū'
>>> Japans.naarJapans(2025, uitspraak=True)
'ni-sen ni-jū go'
>>> Japans.naarJapans(10000, uitspraak=True)
'ichi-man'
>>> Japans.naarJapans(9836703, uitspraak=True)
'kyū-hyaku hachi-jū san man, roku-sen nana-hyaku san'
>>> Japans.naarJapans(1234567890, uitspraak=True)
'jū ni oku, san-sen yon-hyaku go-jū roku man, nana-sen hachi-hyaku kyū-jū'
>>> Japans.naarJapans(2036521801, uitspraak=True)
'ni-jū oku, san-sen roku-hyaku go-jū ni man, sen hachi-hyaku ichi'
>>> Japans.vanJapans('零')
0
>>> Japans.vanJapans('十一')
11
>>> Japans.vanJapans('十七')
17
>>> Japans.vanJapans('百五十一')
151
>>> Japans.vanJapans('三百二')
302
>>> Japans.vanJapans('四百六十九')
469
>>> Japans.vanJapans('二千二十五')
2025
>>> Japans.vanJapans('一万')
10000
>>> Japans.vanJapans('九百八十三万六千七百三')
9836703
>>> Japans.vanJapans('二十億三千六百五十二万千八百一')
2036521801

>>> getal1 = Japans('百二十三')
>>> int(getal1)
123
>>> str(getal1)
'百二十三'
>>> getal1
Japans('百二十三')
>>> getal1.uitspraak
'hyaku ni-jū san'
>>> getal1 + Japans(746)
Japans('八百六十九')
>>> 4321 + getal1
Japans('四千四百四十四')
>>> getal1 + 74822
Japans('七万四千九百四十五')
>>> getal1 - 100
Japans('二十三')
>>> 100 - getal1
Traceback (most recent call last):
AssertionError: ongeldig getal
>>> 200 - getal1
Japans('七十七')

>>> Japans(42) * Japans(983)
Japans('四万千二百八十六')
>>> 53 // Japans(17)
Japans('三')
>>> Japans(1653) % 24
Japans('二十一')
>>> Japans(23) ** Japans(5)
Japans('六百四十三万六千三百四十三')

>>> 10 == Japans('十')
True
>>> Japans(17) == 16
False
>>> Japans(17) != 16
True
>>> Japans(10) < Japans(100)
True
>>> Japans(200) <= 1000
True
>>> Japans(10) > Japans(100)
False
>>> Japans(200) >= 1000
False