Seite 1 von 2

Zahlen zu römische Zahlen wandeln...

Verfasst: Donnerstag 4. Dezember 2008, 09:41
von jens
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...

Verfasst: Donnerstag 4. Dezember 2008, 10:47
von DeJe
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

Verfasst: Donnerstag 4. Dezember 2008, 10:50
von jens
Ja, das stimmt. Würde ich eigentlich auch so machen ;)

Verfasst: Donnerstag 4. Dezember 2008, 11:23
von rayo
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

Verfasst: Donnerstag 4. Dezember 2008, 18:57
von SigMA
Naja die römischen Zahlen sind nun mal nicht "iv" und "iii" sondern "IV" und "III"

Gruß

Verfasst: Donnerstag 4. Dezember 2008, 19:07
von DeJe
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. ;)

Verfasst: Samstag 6. Dezember 2008, 11:57
von sma
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

Verfasst: Montag 22. Dezember 2008, 20:47
von roschi
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

Verfasst: Sonntag 28. Dezember 2008, 19:27
von Nagila Hawa
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).

Verfasst: Sonntag 28. Dezember 2008, 21:54
von Leonidas
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)

Verfasst: Sonntag 28. Dezember 2008, 23:11
von lunar
Das gab es übrigens schon fertig: roman.py. DiveIntoPython-Lesern müsste das bekannt sein ...

Verfasst: Sonntag 28. Dezember 2008, 23:29
von BlackVivi
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.

Verfasst: Montag 29. Dezember 2008, 08:01
von audax
daher fehlt dir auch __radd__, etc....

Verfasst: Montag 29. Dezember 2008, 14:14
von Darii
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? :)

Verfasst: Montag 29. Dezember 2008, 23:25
von Nagila Hawa
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. :(

Verfasst: Montag 29. Dezember 2008, 23:37
von audax
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.).

Verfasst: Montag 29. Dezember 2008, 23:50
von BlackVivi
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.

Verfasst: Dienstag 30. Dezember 2008, 01:32
von Leonidas
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.

Verfasst: Dienstag 30. Dezember 2008, 02:23
von name
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/

Verfasst: Dienstag 30. Dezember 2008, 03:43
von DasIch
Fehlen nur noch vergleiche ;)