Römische Zahlen

Xalon

New member
#1
Hi,
die folgende Aufgabe stammt von lagalopex (Danke dir) :

Dezimale Zahlen in Römische Zahlen umwandeln

Bei Wikipedia ( http://de.wikipedia.org/wiki/Römische_Zahlen ) werden mehrere Arten der
Umwandlung beschrieben, daher wird die Aufgabe wie folgt eingeschränkt:

1. Es werden nur die unter "Darstellung" genannten Werte I ... A benutzt.
2.1 einfache Variante: Es wird die "Einfachen Umrechnung" genutzt.
2.2 erweiterte Variante: Anwendung der "Subtraktionsregel" (wobei 39 == XXXIX)

Es ist ein Programm zu schreiben das eine eingegebene Zahl in römischen Ziffern ausgibt.


Happy Coding,
Xalon
 

ivegotmail

Member of Honour
#2
Code:
#!/usr/bin/clisp
(format t "Zahl eingeben: ")
(write (format nil "~@R" (read)))
:p
 
#3
Im Grunde kam diese Aufgabe (als Anfrage, da er es selber nicht hinbekam^^) mal vorm Jahr oder so von einem Klassenkamerad, daher hab ich natürlich auchschon eine Lösung (in C++). Werde aber wohl noch etwas warten, da es eine noch recht einfache Übung ist, von der man aber durch aus lernen kann (sofern man es selber implentiert und es nicht von der Programmiersprache erledigen lässt... *zu-ivegotmail-schiel*)


btw... Xalon... überprüf mal deine links in der Signatur...
 
#5
So ich hab mich ma rangesetzt.

Ich weiß ist nicht so das gelbe vom Ei, aber es sollte alles funzen^^.

Die eine Zeile ist natürlich nur fürs debuggen gedacht... es gab - wie immer - logische Denkfehler. Sollte da immer noch ein Fehler drin sein, schieb ichs einfach mal auf die Uhrzeit.

mfg,
crack

//edit:
aso 2 Sachen die ich grad noch vergessen hab.

1. -> Alles in Delphi mitm Borland Compiler
2. -> Der erste Anhang ist die .exe und der zweite der Source.

So und nun gn8, hat aber Spaß gemacht !

//edit2:
grml doch nochn Fehler gefunden. Ne 9 ist bei mir kein IX sondern ein VIIII... egal^^, mach ich Morgen weiter. Ma sehn vielleicht hat mich bis dahin ja schon jemand verbessert.
 
#6
Hier mal eine Additionsversion in PHP.

PHP:
<?php
$romZahl = 1984;
$arrRoemisch = array('I' => 1,
                     'V' => 5,
                     'X' => 10,
                     'L' => 50,
                     'C' => 100,
                     'D' => 500,
                     'M' => 1000,
                     'A' => 5000
                    );
                    
$arrTypen = array();
$arrRom = array_keys($arrRoemisch);
$j = 7;
$check = true;

while($check) {
    if ($romZahl >= $arrRoemisch[$arrRom[$j]]) {
        $romZahl-= $arrRoemisch[$arrRom[$j]];
        $arrTypen[$arrRom[$j]]+=1;
        $strRom.=$arrRom[$j];    
    }
    
    if ($romZahl < $arrRoemisch[$arrRom[$j]]) {
            $j--;
    }        
      
    if ($romZahl == 0) {
            $check = false;
        }
}

print_r($arrTypen);                    
echo '<br />'.$strRom;

?>
 
#7
@ BasicAvid:
Ist bei dir genau das selbe Problem.
Dein Script spuckt nämlich
MDCCCCLXXXIIII

statt
MDCCCCLXXXIV
aus.

Genau wie bei mir^^
Naja hab noch nicht weitergemacht, bin jetzt erstmal bis zum Abend weg. Man sieht sich!

mfg,
crack
 
#8
Daher gibt es ja die einfache Version!
Wenn die einfache funktioniert muss man nur etwas weiterdenken und man hat die schwere auch recht schnell!
Man kann dies mit der Einführung von Ziffern für 4, 40, 400 (IV, XL, CD) und 9, 90, 900 (IX, XC, CM) vergleichen
 

CDW

Moderator
Mitarbeiter
#10
MASM (sollte in NASM nicht anders aussehen ;) ), 16-Bit DOSe kompatibel. Assemblierbar mit einer älteren MASM Version per "ml rom.asm /AT". Bei den neueren müsste man tricksen.
Subtraktionsregel. Umrechnung von String zum Integer gleich mitbegriffen. Maximale Eingabe ist 0xFFFF bzw 65535 ;).
Code:
CSEG segment
org 100h
MAX_INPUT equ 10
Begin:
   ;//Einlesen
    mov ah,0ah
    mov dx,offset input
    int 21h
    ;gleich einen Zeilenumbruch nachschieben
     mov ah,06
     mov dl,10
     int 21h

    ;umrechenen Ascii2Number
     mov bx,offset input
     xor cx,cx
     mov cl,byte ptr[bx+1] ;wieviele Zeichen eingelesen
    
     add bx,1 ;offset in position bringen
     add bx,cx

     xor ax,ax
     mov di,1
     xor si,si
     
     ASCII2WORD_LOOP:
        xor ax,ax
        mov al,byte ptr [bx]
        sub al,'0' 
        mul di
        add si,ax
        mov ax,di
        mov di,10
        mul di
        mov di,ax      
        dec bx
        dec cx       
      jnz ASCII2WORD_LOOP
;in SI ist jetzt die umgerechnete Eingabe
;jetzt römisch ausgeben (subtraktionsform)    


mov ax,si
mov si,offset rom
mov di, offset dez
mov cx,14 ;anzahl der Zahlen

WORD2ROM_LOOP:
   mov bx,di
   mov dx,[bx] ;zahl
   mov bx,dx
   xor dx,dx
   div bx
   ;ergebnis: in AX Anzahl der Buchstaben zum Ausgeben, DX ist der Rest, der verbleibt
   test ax,ax
   push dx
   jz @f ;wenn 0, dann nichts ausgeben
   
   push cx
   mov cx,ax
   
   OUT_LOOP:
    mov ah,9
    mov dx,si
    int 21h
   loop OUT_LOOP   
   pop cx
   
   @@:
   pop ax  ;werte tauschen
   add si,3
   add di,2
   loop WORD2ROM_LOOP
   ;konsole nciht gleich schließen
   int 20h

rom db "A$",0,"M$",0,"CM$","D$",0,"CD$","C$",0,"XC$","L$",0,"XL$","X$",0,"IX$","V$",0,"IV$","I$"
dez dw 5000,1000,900,500,400,  100, 90,  50,  40, 10, 9,         5,   4, 1
input db MAX_INPUT
CSEG ends
end Begin
Wem der Code etwas seltsam erscheint: es gelten die 8086 Einschränkungen (zumindest laut dem Assembler :rolleyes: ). Und wenn man bedenkt, dass hier auch gleich die String2Int routine mit drinsteckt, ist es auch nicht so viell Code ;)

Im Anhang die fertige Binary, die rund 10 mal kleiner ist, als der Quellcode (das fesselt mich so an dieses format - nichts überflüssiges ). Nach dem Download die Endung "TXT" abschneiden.

Und wer sich gar nciht für sowas begeistern kann:Ja, ich jage gerne meinen Elefanten auf Händen und Knien *fg*
 
#13
Original von lagalopex
Original von Mc Goodi
darf bei den römischen ziffern afaik ein buchstabe nicht höchstens 3 mal hintereinander stehen? also wegen cccc meine ich
Das stimmt nur, wenn man die Subtraktionsregel nicht anwendet! (Was im einfachen Fall der Aufgabenstellung entspricht)
Japp sorry, hatte den Artikel von Wikipedia nicht gelesen sondern hab einfach gedacht die Schreibweise wäre falsch weil es mir - wie Mc Goodi es schon sagte - auch so beigebracht wurde. In dem Fall ist natürlich auch das Vierfache C falsch.
 
#14
Eine PHP funktion. Kann wahlweise verkürzen oder nicht.

PHP:
<?php

	
	echo "1984 - ".Roemisch(1984,False)." - ".Roemisch(1984)."<br>";
	echo "2006 - ".Roemisch(2006,False)." - ".Roemisch(2006)."<br>";
	echo "5000 - ".Roemisch(5000,False)." - ".Roemisch(5000)."<br>";
	
	
	
	Function Roemisch($Wert,$Kurz=True)
	{
		$Zahlen[0]=array(1		,"I"	,1);
		$Zahlen[1]=array(5		,"V"	,5);
		$Zahlen[2]=array(10		,"X"	,1);
		$Zahlen[3]=array(50		,"L"	,5);
		$Zahlen[4]=array(100	,"C"	,1);
		$Zahlen[5]=array(500	,"D"	,5);
		$Zahlen[6]=array(1000	,"M"	,1);
		$Zahlen[7]=array(5000	,"A"	,5);
	
	
		//Unverkürzt berechnen
		For($Nummer=count($Zahlen)-1;$Nummer>-1;$Nummer--)
		{
			
			While($Wert>=$Zahlen[$Nummer][0])
			{
				$Wert=$Wert-$Zahlen[$Nummer][0];
				$Ausgabe=$Ausgabe.$Zahlen[$Nummer][1];
			}
			
			
		}
		//Kürzen
		IF($Kurz==True)
		{
			For($Nummer=count($Zahlen)-2;$Nummer>-1;$Nummer--)
			{	
				// "9" berücksichtigen
				IF($Zahlen[$Nummer][2]==5)
				{
					$Ausgabe=ereg_replace($Zahlen[$Nummer][1].$Zahlen[$Nummer-1][1].$Zahlen[$Nummer-1][1].$Zahlen[$Nummer-1][1].$Zahlen[$Nummer-1][1],$Zahlen[$Nummer-1][1].$Zahlen[$Nummer+1][1],$Ausgabe);
				}
				
				// "4" berücksichtigen
				$Ausgabe=ereg_replace($Zahlen[$Nummer][1].$Zahlen[$Nummer][1].$Zahlen[$Nummer][1].$Zahlen[$Nummer][1],$Zahlen[$Nummer][1].$Zahlen[$Nummer+1][1],$Ausgabe);
			}
		}
		return $Ausgabe;
	}

?>
 

mig

New member
#19
hi,
hier mal ne Java-Version:

Code:
import Prog1Tools.IOTools;
public class rom {
	public static void main(String [] args) {
		int eingabe = IOTools.readInteger();
		abfrage(eingabe,false); //Einfache Umrechnung
		abfrage(eingabe,true);	//Subtraktionsregel
	}

	public static void abfrage (int eingabe2,boolean b){
		String sub = "";
		boolean a = true;
		while(a){	
			if(eingabe2 >= 1000) {
				eingabe2 = eingabe2 - 1000;
				sub = sub + 'M';
			}
			else if(eingabe2 >=900 && b){
				eingabe2 = eingabe2 - 900;
				sub = sub+"CM";
			}
			else if(eingabe2 >= 500) {
				eingabe2 = eingabe2 - 500;
				sub = sub + 'D';
			}
			else if(eingabe2 >=400 && b){
				eingabe2 = eingabe2 - 400;
				sub =sub+"CD";
			}				
			else if(eingabe2 >= 100) {
				eingabe2=eingabe2 - 100;
				sub = sub + 'C';
			}
			else if(eingabe2 >=90 && b){
				eingabe2 = eingabe2 - 90;
				sub = sub+"XC";
			}
			else if(eingabe2 >= 50) {
				eingabe2=eingabe2 - 50;
				sub = sub + 'L';
			}
			else if(eingabe2 >=40 && b){
				eingabe2 = eingabe2 - 40;
				sub = sub+"XL";
			}
			else if(eingabe2 >= 10) {
				eingabe2=eingabe2 - 10;
				sub = sub + 'X';
			}
			else if(eingabe2 >=9 && b){
				eingabe2 = eingabe2 - 9;
				sub = sub+"IX";
			}
			else if(eingabe2 >= 5) {
				eingabe2=eingabe2 - 5;
				sub = sub + 'V';
			}
			else if(eingabe2 >=4 && b){
				eingabe2 = eingabe2 - 4;
				sub = sub+"IV";
			}
			else if(eingabe2 >= 1) {
				eingabe2=eingabe2 - 1;
				sub = sub + 'I';
			}
			else if(eingabe2 == 0){
				System.out.println(sub);
				a = false;
			}
		}
	}
}
 
Oben