Zahlen zu römische Zahlen wandeln...

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Letztens hätte ich es gebrauchen könne, nun hab ich es gefunden:

Code: Alles auswählen

def format_roman(case, counter):
    ones = ['i', 'x', 'c', 'm']
    fives = ['v', 'l', 'd']
    label, index = '', 0
    # This will die of IndexError when counter is too big
    while counter > 0:
        counter, x = divmod(counter, 10)
        if x == 9:
            label = ones[index] + ones[index+1] + label
        elif x == 4:
            label = ones[index] + fives[index] + label
        else:
            if x >= 5:
                s = fives[index]
                x = x-5
            else:
                s = ''
            s = s + ones[index]*x
            label = s + label
        index = index + 1
    if case == 'I':
        return label.upper()
    return label

for i in xrange(20):
    print format_roman("I", i)
Ausgabe:
I
II
III
IV
V
VI
VII
VIII
IX
X
XI
XII
XIII
XIV
XV
XVI
XVII
XVIII
XIX
Ist allerdings nicht von mir, sondern steckt in den Standard lib im formatter.AbstractFormatter ;) Hab es nur aus der Klasse herraus gelöst.

Ist nicht in der Doku erwähnt, siehe: http://docs.python.org/dev/library/form ... -formatter

Dumm finde ich das mit dem .upper() irgendwie komisch gemacht, statt True/False zu nehmen...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

Das finde ich auch unglücklich.
Mir gefällt auch die Reihenfolge der Parameter nicht.

Code: Alles auswählen

def format_roman(counter, upper_case=True):
    ...
    return label.upper() if upper_case else label
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ja, das stimmt. Würde ich eigentlich auch so machen ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Warum upper() überhaupt in der Funktion aufrufen? Ich finde das gehört absolut nicht in diese Funktion.

Falls das einer braucht kann er immernoch format_roman(zahl).upper() aufrufen.

Gruss
Benutzeravatar
SigMA
User
Beiträge: 181
Registriert: Sonntag 4. April 2004, 13:27
Wohnort: Freiburg
Kontaktdaten:

Naja die römischen Zahlen sind nun mal nicht "iv" und "iii" sondern "IV" und "III"

Gruß
Leichtdio.de - Das Kreativ-Blog
http://www.leichtdio.de
DeJe
User
Beiträge: 39
Registriert: Sonntag 23. November 2008, 19:38

So ist es.
Deshalb wäre (laufzeitoptimiert) folgende Variante wahrscheinlich sowieso sinnvoller:

Code: Alles auswählen

def format_roman(counter, upper_case=True):
    ones = ['I', 'X', 'C', 'M']
    fives = ['V', 'L', 'D']
    ...
    return label if upper_case else label.lower()
Naja, sooo viel macht das ja nicht aus. ;)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Nur echt wäre der Algorithmus ja, wenn er die Unicode-Symbole U+2160 bis U+2180 benutzen würde :) Python 3 kann die sogar auch mit upper() und lower() ineinander überführen, erkennt sie aber weder als Buchstaben noch als Ziffern. Komische Biester.

Auf dem Mac ist übrigens deren Kerning kaputt. Obwohl ich den nicht-proportionalen Font Monaco im Terminal benutze, laufen die Zeichen ineinander. Grummel.

Stefan
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

hallo!

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

"""This module converts Roman numerals
into integers and also reversed.
The numbers must be in range 1...4999!

Methods:
 rtoi    - Roman number -> Integer
 itor    - Integer -> Roman number

Example:
>>> rtoi('XVI')
<<< 16
>>> itor(16)
<<< 'XVI'"""

import re

class OutOfRangeError(Exception): pass
class NotIntegerError(Exception): pass
class InvalidRomanNumeralError(Exception): pass

MAX_ROMAN_NUMERAL = 4999

RomanNumeralMap = (('M', 1000), ('CM', 900), ('D', 500),
                   ('CD', 400), ('C', 100), ('XC', 90),
                   ('L', 50), ('XL', 40), ('X', 10),
                   ('IX', 9), ('V', 5), ('IV', 4),
                   ('I',  1))

ValidRomanNumeralPattern = re.compile( \
 """
 ^
 M{0,4}            # thousands - 0 to 4 M's
 (CM|CD|D?C{0,3})  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
                   # or 500-800 (D, followed by 0 to 3 C's)
 (XC|XL|L?X{0,3})  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
                   # or 50-80 (L, followed by 0 to 3 X's)
 (IX|IV|V?I{0,3})  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
                   # or 5-8 (V, followed by 0 to 3 I's)
 $
 """, re.VERBOSE)

def itor(n):
  """itor(int) -> string
     Converts integers to Roman numbers"""

  if not (0 < n < 5000):
    raise OutOfRangeError, "number out of range (must be 1...%s)" \
                           % MAX_ROMAN_NUMERAL
  if int(n) <> n:
    raise NotIntegerError, "non-integers can not be converted"
  result = ""
  for num, i in RomanNumeralMap:
    while n >= i:
      result += num
      n -= i
  return result

def rtoi(s):
  """rtoi(string) -> int
     Converts Roman numbers to integers"""

  if not s:
    raise InvalidRomanNumeralError, "Input can not be blank"
  if not ValidRomanNumeralPattern.search(s):
    raise InvalidRomanNumeralError, "Invalid Roman numeral: '%s'" % s

  result = 0
  index = 0
  for num, i in RomanNumeralMap:
    while s[index:index+len(num)] == num:
      result += i
      index += len(num)
  return result
hab ich mir mal zusammengebastelt.
vorlage war ein beispiel aus 'dive into python'.

lg
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
Nagila Hawa
User
Beiträge: 16
Registriert: Montag 9. Juni 2008, 18:20
Kontaktdaten:

Moin!

Beim Range Check fehlt die Konstante MAX_ROMAN_NUMERAL.

Ich finde das immer eine gute Übung. Ich bin auch gerade dabei (allerdings in Ada) einen eigenen Datentyp "Roman" zu schreiben, mit dem man dann ganz normal, wie mit jedem numerischen Datentyp rechnen kann (obwohl es technisch gesehen ein String ist).
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Nagila Hawa hat geschrieben:Ich finde das immer eine gute Übung. Ich bin auch gerade dabei (allerdings in Ada) einen eigenen Datentyp "Roman" zu schreiben, mit dem man dann ganz normal, wie mit jedem numerischen Datentyp rechnen kann (obwohl es technisch gesehen ein String ist).
Stimmt, mit Python wäre so eine Übung ja zugegebenermaßen auch etwas zu trivial 8)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

Das gab es übrigens schon fertig: roman.py. DiveIntoPython-Lesern müsste das bekannt sein ...
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Leonidas hat geschrieben:
Nagila Hawa hat geschrieben:Ich finde das immer eine gute Übung. Ich bin auch gerade dabei (allerdings in Ada) einen eigenen Datentyp "Roman" zu schreiben, mit dem man dann ganz normal, wie mit jedem numerischen Datentyp rechnen kann (obwohl es technisch gesehen ein String ist).
Stimmt, mit Python wäre so eine Übung ja zugegebenermaßen auch etwas zu trivial 8)
http://paste.pocoo.org/show/97096/

Äußerst trivial, jop. Nicht perfekt, weit davon entfernt, aber einfach so ohne zu überlegen in nichmal 2 Minuten zusammenprogrammiert.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

daher fehlt dir auch __radd__, etc....
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

sma hat geschrieben:Auf dem Mac ist übrigens deren Kerning kaputt. Obwohl ich den nicht-proportionalen Font Monaco im Terminal benutze, laufen die Zeichen ineinander. Grummel.
Laut Wikipedia sind sie nur zur Kompatibilität gedacht und nicht zur Benutzung in Schriften mit Horizontaler Schreibrichtung vorgesehen, vielleicht liegts daran? :)
Nagila Hawa
User
Beiträge: 16
Registriert: Montag 9. Juni 2008, 18:20
Kontaktdaten:

Wow, das ist ja wirklich winzig das Modul! Ich glaube ich muß mal öfter mit Python arbeiten, damit ich das überhaupt verstehe und Python wirklich ausnutzen kann (derzeit sehen Python-Programme bei mir meistens recht konservativ aus...). :D

Dazu fällt mir dann aber eine eher allgemeine Frage ein: Ich komme nicht wirklich hinter das Typensystem von Python, oder allgemein dynamisch typisierten Sprachen. Inwiefern ist bei so einem Konstrukt denn eigentlich Typsicherheit gewährt? Wie funktioniert das, was macht der Interpreter? Gibt es irgendwo vielleicht eine Art Doku speziell über Typisierung und erstellen eigener Typen in Python? In Tutorials ist das meistens recht kurz gefasst. Das Typsystem in Ada ist ja auch recht mächtig und eigen, aber das lernt man da von der Pike an und ist daher in Tutorials recht genau erläutert (ohne dem lässt sich auch schlecht arbeiten...), in Python habe ich mich noch nicht so damit auseinandergesetzt.

Vielleicht bin ich auch einfach von der strikten Struktutr streng typisierter Sprachen wie Ada oder von gefährlichen Typ-Mißbrauch-Sprachen wie C zu sehr beeinflußt worden, um Python jemals richtig zu lernen. :(
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Python ist stark und dynamisch Typisiert.
Jedes Objekt hat einen festet Typ, der aber nicht überprüft wird (von Sprachwegen her jedenfalls, von manuellen Tests hält einen ja niemand ab.).
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

audax hat geschrieben:daher fehlt dir auch __radd__, etc....
Lässt sich wohl bei Bedarf recht flott hinzufügen, oder ;)? Hab jetzt nur die 4 Grundrechenarten und die Repräsention geändert, mehr nicht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Nagila Hawa hat geschrieben:Dazu fällt mir dann aber eine eher allgemeine Frage ein: Ich komme nicht wirklich hinter das Typensystem von Python, oder allgemein dynamisch typisierten Sprachen. Inwiefern ist bei so einem Konstrukt denn eigentlich Typsicherheit gewährt? Wie funktioniert das, was macht der Interpreter? Gibt es irgendwo vielleicht eine Art Doku speziell über Typisierung und erstellen eigener Typen in Python? In Tutorials ist das meistens recht kurz gefasst.
Schau dir beliebige Tutorials zu OOP in Python an (vom Openbook vielleicht mal abgesehen). Generell hast du Klassen die Typen definieren und dann Instanzen dieser Klassen, die halt die Objekte sind (vereinfacht gesagt, es geht dann noch weiter, dass Klassen auch Objekte sind und diese Klassen auch Instanzen ihrer Metaklassen sind etc.). Diesen Objekten kann man dann Nachrichten schicken wie "gib mir den Wert von Attribut x" oder "setze den Indexwert 0 auf 'String'" und die Objekte reagieren darauf irgendwie.

Wenn dich die Hintergründe Interessieren kannst du dir das Descrintro ansehen und die C3 MRO. Zusätzlich zu den bereits angesprochenen Tutorials.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

BlackVivi hat geschrieben:
Leonidas hat geschrieben:
Nagila Hawa hat geschrieben:Ich finde das immer eine gute Übung. Ich bin auch gerade dabei (allerdings in Ada) einen eigenen Datentyp "Roman" zu schreiben, mit dem man dann ganz normal, wie mit jedem numerischen Datentyp rechnen kann (obwohl es technisch gesehen ein String ist).
Stimmt, mit Python wäre so eine Übung ja zugegebenermaßen auch etwas zu trivial 8)
http://paste.pocoo.org/show/97096/

Äußerst trivial, jop. Nicht perfekt, weit davon entfernt, aber einfach so ohne zu überlegen in nichmal 2 Minuten zusammenprogrammiert.
Naja, es sollt doch Roman("IV") + Roman("I") gehen, oder?

EDIT: Here we go: http://paste.pocoo.org/show/97252/
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Fehlen nur noch vergleiche ;)
Antworten