Kategorien
PHP

Römische Zahlen

In einem Internet-Wettbewerb bin ich über die Herausforderung gestolpert, in möglichst wenig Code eine saubere Funktion zur Umrechnung von römischen Zahlen ins mittlerweile doch schon etwas länger übliche Dezimalsystem zu schreiben. Da eine meiner größten Schwächen ist, solche Herausforderungen fast blind anzunehmen, konnte ich natürlich nicht widerstehen.

Zwei Stunden später war folgende PHP-Funktion fertig:

[php]
<?php
function roman_to_decimal($roman) {
// definie the roman values
$a=array(0=>array("I"=>1, "V"=>5, "X"=>10, "L"=>50, "C"=>100, "D"=>500, "M"=>1000));
// clean up the given statement – you’ll never know…!
$roman = trim(strtoupper($roman));
// make an array out of the given statement
$x=str_split($roman);
$l=strlen($roman)-1;
// convert letters to numbers
for($y=0;$y<=$l;++$y) { $x[$y]=$a[0][$x[$y]]; }
// do the math work…
for($y=0;$y<=$l;++$y) {
if($x[$y]<$x[$y+1]) { $x[$y]*=-1; }
$r+=$x[$y];
}
// return calculated value
$decimal = "nullum";
if ($r>0) { $decimal = $r; }
return $decimal;
}
// ————————————————-
// how to use it…
// ————————————————-
$r = "MCXXX";
echo "Roman: ".$r." — Decimal: ".roman_to_decimal($r); ?>
[/php]

Zusammengeschrumpft hat die Funktion dann ca. 250 Bytes – ich persönlich fand das nicht schlecht. Andere Funktionen waren jedoch lediglich nur halb so groß! Wie soll das bloß gehen? Naja, zumindest funktioniert meine Funktion einwandfrei… ist ja auch etwas wert!

Von Björn

Tja, ich bin Schöpfer und Admin von dieser Seite!

13 Antworten auf „Römische Zahlen“

Nach wieder einigen Jahren.. ein ganz anderer Ansatz und ganz ohne Mathe:
function r($r){
$a=array(„IV“,“IX“,“XL“,“XC“,“CD“,“CM“,“I“,“V“, „X“, „L“,“C“,“D“,“M“);
$b=array(„4+“,“9+“,“40+“,“90+“,“400+“,“900+“,“1+“,“5+“,“10+“,“50+“,“100+“,“500+“,“1000+“);
$b=str_ireplace($a,$b,$r).“0″;
return eval(„return $b;“);}

Viele Grüße,
Joscha

Hehe, mein Code ist drei Jahre alt, ist innerhalb von etwa 60min an einem viel zu frühen Samstag Vormittag entstanden. Vielen Dank für die guten Ergänzungen!

$a=array(0=>array(„I“=>1, …
Wozu ist in diesem array noch ein array?
Dadurch hast du in der for Schleife
$a[0][$x[$y]]

Ein array wie „$a=array(„I“=>1…“ würde ausreichen und in der for-Schleife dann ‚$a[$x[$y]]‘ verwenden ist viel kürzer.

$r sollte auch vor der Schleife deklariert werden
und in der Zeile
if($x[$y]<$x[$y+1]) { $x[$y]*=-1; }
wird beim letzten Element im array $x mit $x[$y+1] auf ein nicht existierendes Index zugegriffen. Sollte vorher auf Existenz geprüft werden.
Mit return $r ? $r : $decimal; sparst du dir wieder die if Abfrage davor.

if($x[$y]<$x[$y+1]) <<- Warum +1?
{
$x[$y]*=-1;
<<-Warum *=1? Was heißt das?

Der Dezimalwert von römische Zahlen ist abhängig von der Positionierung. Um nun festzustellen, wie ich mit der Zahl zu rechnen habe, muss ich diese also mit dem Wert der nächsten Zahl vergleichen. Beispiel XI und IX. Bei XI rechne ich 10 + 1 (=11). Wenn aber nun 1 vor der 10 steht (IX) dann muss ich den Wert der vorangegangenen Ziffer abziehen. Die if-Klausel prüft, ob der vorangestellte Wert kleiner ist, das *=-1 dreht das Vorzeichen in diesem Fall, sodass in das Ergebnis $r nur noch den Wert addiert werden muss.

$l=strlen($roman)-1; <<- warum -1?

Die Länge der Zeichenfolge benötige ich für den Berechnungsloop (die for-Schleifen). Wenn ich -1 weglassen würde, dann müsste ich die for-Kommandos auf for($y=0;$y<$l;++$y) verändern. Warum ich das damals so gemacht habe, weiß ich nicht mehr so genau, aber es sollte beides gehen – und es gibt sicherlich noch bessere Methoden, die Länge zu ermitteln.

Ja , das habe ich soweit verstanden.
Was ich nicht ganz verstehe ist der mathetische teil.

// do the math work…
for($y=0;$y<=$l;++$y)
{
if($x[$y]<$x[$y+1]) <<- Warum +1?
{
$x[$y]*=-1; <<-Warum *=1? Was heißt das?
}
$r+=$x[$y];
}

Und

$l=strlen($roman)-1; <<- warum -1?

Tut mir leid, wenn die fragen etwas doof sind, aber ich bin nueling in den thema php und meine kenntnisse sind sehr begrenzt.

Hallo Bambuu,

naja, Sinn der Übung war damals (und das ist schon zwei Jahre her), einen möglichst komprimierten Code zu haben. Prinzipiell hat der Codeblock fünf Bestandteile:
1) Definition der Römischen Zeichen,
2) Vorbereiten des Input und Wandeln in ein Array,
3) Wandeln der Zeichen in die korrespondierenden Zahlen,
4) Wert berechnen,
5) Rückgabe.

Wo genau verstecken sich Ihre Verständnisfragen?

Grüße,
Björn

Könnten sie vllt. eine vollständige erklärrung für jeden schritt einfügen, da ich nicht ganz verstehe was sie dort gemacht haben.

Hm, waere jetzt noch interessant die anderen Ergebnisse zu sehen – gibts die Contestdaten auf irgendner Website zu bestaunen?

Grosses Lob von meiner Seite, dein Blog gefaellt mir sehr gut
Hoffentlich folgen noch weitere Beitraege, ich bin auf jedenfall gespannt
Viele Gruesse, Simon

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.