Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Algorithmus Umwandlung dezimale Zahlen in römische und umgekehrt

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
26.09.2003, 20:00 Uhr
~Steven23
Gast


Moin Leute!

Ich habe ein kleines Problem. Ich muß fürs Studium eine Hausarbeit in C++ schreiben, und komme da nicht weiter. Ich soll ein Programm schreiben, mit dem man römische Zahlen in Dezimalzahlen (1-3999) umwandelt und umgekehrt. Das in C++ zu programmieren wäre kein Problem, nur leider habe ich bisher noch keinen passenden Algorithmus gefunden. Ich hoffe ihr könnt mir helfen.
Danke im voraus
MfG Steven
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
26.09.2003, 21:59 Uhr
BeS



Hallo,
das scheint eine beliebte Aufgabe zu sein, habe ich auch im 1.Semester machen dürfen.
Den Algorithmus (pseudo-code) hätte ich noch, zumindest in die eine Richtug dezimal->römisch, aber dann ist ja der ganze Spaß weg...

Der Sinn der Aufgabe ist ja das du einen Alogorithmus entwirfst und nicht das du zeigst das du die 3 C++ Befehle kannst um es zu programmieren...
--
If art interprets our dreams, the computer execute them in the guise of programs!

Dieser Post wurde am 26.09.2003 um 22:10 Uhr von BeS editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
26.09.2003, 23:03 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


Hey das ist ne geil sache daraus können wir doch zwei golfrätsel machen

1)Schreibe ein programm das eine dezimalzahl übergeben bekommt und dies als römische zahl ausgibt und
2) umgekehrt
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
26.09.2003, 23:27 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


@Steven23
bis Sonntag abend hat das ja noch hoffentlich zeit.
Bis dahin bekommst du dann spätestens deine Lösung falls du es nicht selbst schaffst
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
27.09.2003, 12:58 Uhr
~(un)wissender
Gast


Habe das noch in Java irgendwo rumfliegen, in C++ könnte ich das bis heute abend fertig machen, erst muss ich noch Mittags essen, dann schlafen, dann Tee trinken...
Dann feiern (Kramermarkt in Oldenburg, he)!
Ich weiß aber nicht, ob dir das hilft, denn der Algo ist nicht wirklich schwer.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
27.09.2003, 12:59 Uhr
0xdeadbeef
Gott
(Operator)


Was ist dein Ansatz? Der Sinn der Hausarbeit ist ja, denke ich, schon, dass du das selbst hinkriegst.

Für ne Beschreibung der entsprechenden Algorithmen würd ich mal google fragen. Die Geschichte ist im Grunde aber ziemlich simpel.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 27.09.2003 um 13:00 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
27.09.2003, 14:58 Uhr
~Steven23
Gast


Den Quellcode brauche ich eigentlich nicht, proggen kann ich dann selber. Meine bisherige Idee: als char array einlesen, falls dez in -> int variable umwandeln, die int var dann durch die jeweiligen römischen zahlen von oben nach unten (also angefangen mit 1000, 500, usw.) teilen, falls reinpasst ausgeben, von der int var die ausgebene summe abziehen Problem:
zahlen wie 3999, 9, 4, 49, 99 usw. wegen IV, IX, IM

andersherum könnte ich ja einfach den array abfragen, und in int var addieren, aber auch hier wieder das problem mit IV, IX, IM usw.

Danke für die bisherigen Antworten
MfG
Steven
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
27.09.2003, 15:38 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


Das mit dem einfach draufaddieren sollte eigentlich gehen
Am Ende musst du nur nochmal drüber laufen ob es ein C gibt das vor einem M oder D ist. Wenn ja 200 abziehen
Dann noch gucken ob es ein X gibt das vor einem C oder L ist, wenn ja20 abziehen und dann noch schauen ob es ein I gibt das vor einem X oder V ist, wenn ja 2 abziehen
fertig
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
28.09.2003, 00:01 Uhr
~(un)wissender
Gast


So, recht ausführlich
Wer Fehler findet darf sie behalten!



C++:
#include <iostream>
#include <sstream>
#include <string>
#include <cctype>
using namespace std;

class RomanDigit {
    public:
        const string decimalToRoman(unsigned int decDigit) throw();
        const string romanToDecimal(const string& romDigit) throw();
    private:
        unsigned int computeDecimalValue(const string& romDigit) throw();
};


//Eine Dezimalzahl in eine römische Zahl umrechnen.
const string RomanDigit :: decimalToRoman(unsigned int decDigit) throw()
{
    stringstream ss;
    //Bereich überprüfen
    if(decDigit < 1 || decDigit > 3999)
    {
        ss << "Valide range is 1 - 3999" << "\n" << "Not: " << decDigit << "\n";
        return ss.str();
    }
    
    //1000sender abarbeiten(max 3).
    while(decDigit >= 1000) {
        ss << "M";
        decDigit -= 1000;
    }
    
    //Es kann max. einen 500er geben.
    if(decDigit >= 500) {
        ss << "D";
        decDigit -= 500;
    }
    
    //Es kann nur drei gleiche Buchstanben hintereinander geben.
    //Also 500 weniger 100 = 400
    if(decDigit >= 400) {
        ss << "CD";
        decDigit -= 400;
    } else {
        //Max. dreimal
        while(decDigit >= 100)
        {
            ss << "C";
            decDigit -= 100;
        }
    }
    
    //Es kann max. einen 50er geben.
    if(decDigit >= 50) {
        ss << "L";
        decDigit -= 50;
    }
    
    //Es kann nur drei gleiche Buchstanben hintereinander geben.
    //Also 50 weniger 10 = 40
    if(decDigit >= 40) {
        ss << "XL";  
        decDigit -= 40;      
    } else {
        //Max. dreimal
        while(decDigit >= 10)
        {        
            ss << "X";
            decDigit -= 10;
        }
    }
    
    //Es kann max. einen 5er geben.
    if(decDigit >= 5)  {
        ss << "V";
        decDigit -= 5;
    }
    
    //Es kann nur drei gleiche Buchstanben hintereinander geben.
    //Also 5 weniger 1 = 4
    if(decDigit == 4) {
        ss << "IV";
        decDigit -= 4; //dann Null (obsolet)
    } else {
        //Max. dreimal
        while(decDigit > 0)
        {
            ss << "I";
            --decDigit;
        }
    }
    
    return ss.str();  
}


//Eine römische Zahl in einen Dezimalwert umrechnen.
const string RomanDigit :: romanToDecimal(const string& romDigit) throw()
{      
    if(romDigit.size() == 0)
        return string("Digit is emty, when it should not be!");
        
    stringstream ss;
                  
    //Es wird hier noch nicht die richtige Reihenfolge der römischen Lettern geprüft,
    //sondern nur ob die Lettern existieren  .
    //Vielleicht implemetiert ich den Reihenfolgecheck noch, mal sehen.  
    for(unsigned int i = 0; i < romDigit.size(); ++i)
    {
        if(romDigit[i] != 'M' && romDigit[i] != 'D' && romDigit[i] != 'C' &&
           romDigit[i] != 'L' && romDigit[i] != 'X' && romDigit[i] != 'V' &&
           romDigit[i] != 'I')
       {
            ss << "Invalide roman digit: " << romDigit << "\n" << "Error at: "
               << i << " (" << romDigit[i] << ")" << "\n";
            ss << "Use M = 1000, D = 500, C = 100, L = 50, X = 10, V = 5, i = 1\n";
            return ss.str();
       }
    }
    
    //Umrechnen
    unsigned int decValue = computeDecimalValue(romDigit);
            
    ss << decValue; //Integer in einen String umwandeln.          
    
    //Alles korrekt                    
    return ss.str();
}

unsigned int RomanDigit :: computeDecimalValue(const string& romDigit) throw()
{
    unsigned int decValue = 0;
    unsigned int pos = 0;
  
    while(pos < romDigit.size() && romDigit[pos] == 'M')
    {  
        decValue += 1000;
        ++pos;
    }

    if(pos < romDigit.size() && romDigit[pos] == 'D')
    {  
        decValue += 500;
        ++pos;
    }
    
    //Eine Position vorgreifen, wegen möglicher umgekehrter Notation.
    if(pos + 1 < romDigit.size() && romDigit[pos + 1] == 'D') {
        decValue += 400;
        pos += 2;
    } else {
        while(pos < romDigit.size() && romDigit[pos] == 'C')
        {
            decValue += 100;
            ++pos;
        }
    }
    
    if(pos < romDigit.size() && romDigit[pos] == 'L')
    {  
        decValue += 50;
        ++pos;
    }
    
    if(pos + 1 < romDigit.size() && romDigit[pos + 1] == 'L') {
        decValue += 40;
        pos += 2;
    } else {
        while(pos < romDigit.size() && romDigit[pos] == 'X')
        {
            decValue += 10;
            ++pos;
        }
    }
    
    if(pos < romDigit.size() && romDigit[pos] == 'V')
    {  
        decValue += 5;
        ++pos;
    }
    
    if(pos + 1 < romDigit.size() && romDigit[pos + 1] == 'V') {
        decValue += 4;
        pos += 2; //obsolet
    } else {
        while(pos < romDigit.size() && romDigit[pos] == 'I')
        {
            decValue += 1;
            ++pos;
        }
    }
    
    return decValue;
}

int main(int argc, char *args[])
{
    RomanDigit rD;
    if(argc < 2)
        cout << "Not enough Arguments!";
    else
        if(isdigit(args[1][0]))
            cout << rD.decimalToRoman(atoi(args[1]));
        else
            cout << rD.romanToDecimal(args[1]);
    return 0;
}

 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
28.09.2003, 15:15 Uhr
0xdeadbeef
Gott
(Operator)


Naja, das ist aber schon ziemlich umständlich. Für die arabisch->römisch-Konversion würde ich mir die Strings und korrespondierenden Werte in Arrays aufbewahren und entsprechend zusammenschustern. Du musst auch nicht zwischen if und while unterscheiden, weil in dem Moment, in dem die Bedingung nur einmal wahr sein kann, while dasselbe wie if macht. Wenn wir schon dabei sind, Code zu posten:

C++:
#include <string>
std::string arab2roman(int x) {
  if(x < 1 || x > 3999) throw(x); //nicht darstellbar

  static const char *rom_strings[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" };
  static const int rom_values[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
  std::string ret;
  for(int i = 0; x != 0; ++i)
    while(x >= rom_values[i]) {
      x -= rom_values[i];
      ret += rom_strings[i];
    }

  return ret;
}


Ist jetzt grad mal so hingekladdet, ich denke, das Prinzip wird klar. Die andere Konversion kann man unter denselben Gesichtspunkten verkürzen, aber das wird als Aufgabe für den Leser gelassen
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: