[JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

B

boss3D

Guest
[JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Hi @ all!

Ich habe hier eine Java-Aufgabe, bei der ich nicht ganz verstehe, WAS zu machen ist. Wie das ganze dann code-mäßig aussehen soll, kann ich mir dann schon selbst überlegen (werden wir eh sehen, wie weit ich komme) ...

Capture.JPG

1.) Wie versteht ihr den ersten Punkt? Methoden für Addition, Subtraktion, Multiplikation und Division von römischen Zahlen erstellen? Wo die römischen und dezimalen Zahlen hernehmen? Einlesen per scanner oder gleich ein paar fix definieren?

2.) Ermittlung des numerischen Wertes ist klar. Einfach den dezimalen Wert zu einer beliebigen römischen Zahl ermitteln, nehme ich an?!

3.) Ermittlung der normalisierten Form bezieht sich dann wohl auf die Punkte 4 und 5?! Eine "falsche" römische Zahl gemäß den Regeln in Punkt 4 und 5 korrigieren?! Nur, wie das umsetzen? Das wird ja eine Raterei, welche römische Zahl der User gemeint haben könnte?!

4.) Und was kann ich mir dann unter der Anmerkung nach Punkt 5 vorstellen? Eine römische Zahl wird ja immer als Zeichenkette ein-/angegeben?! Das Gegenteil ist ja dann ein dezimaler int?! Und wieso soll da dann plötzlich eine "falsche" Zeichenkette nicht fehlerbereinigt werden?

^^ Blickt bei der Aufgabe irgendwer durch? :huh:

Vielen Dank für baldige Antworten!
 

DarkMo

Lötkolbengott/-göttin
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

1.) Wie versteht ihr den ersten Punkt? Methoden für Addition, Subtraktion, Multiplikation und Division von römischen Zahlen erstellen? Wo die römischen und dezimalen Zahlen hernehmen? Einlesen per scanner oder gleich ein paar fix definieren?
Na du liest halt meinetwegen ne römische 5 und ne römische 4 ein -> "V" und "IV". da haste schon deine römischen zahlen. die additions methode würde dann szs so aussehen:
string RomanNumber::addition(string a, string b) { ... }
am ende kommt wieder ein string bei raus -> V + IV = IX.

2.) Ermittlung des numerischen Wertes ist klar. Einfach den dezimalen Wert zu einer beliebigen römischen Zahl ermitteln, nehme ich an?!
richtig. das ist ein wichtiger schritt denke ich mal. also aus der "V" machst du ne 5 und aus der "IV" ne 4. eine umkehrfunktion wäre dann noch nicht übel. dann kannst du nämlich aus der additions methode sowas hier machen:
string RomanNumber::addition(string a, string b) { return this.dec2roman( this.roman2dec(a) + this.roman2dec(b) ); }
also, du wandelst die eingegebenen strings in dezimale zahlen um, rechnest mit denen das operations-ergebnis aus, und wandelst dieses wieder in ne römische ziffer (string) um.

3.) Ermittlung der normalisierten Form bezieht sich dann wohl auf die Punkte 4 und 5?! Eine "falsche" römische Zahl gemäß den Regeln in Punkt 4 und 5 korrigieren?! Nur, wie das umsetzen? Das wird ja eine Raterei, welche römische Zahl der User gemeint haben könnte?!
joa, normalisierte form... soll dann aus "ViIi" "VIII" werden? also nen einheitliches format durchgesetzt werden? wobei es da doch sicher string-methoden für gibt. .lower() oder so für alles in kleinbuchstaben. das mit der falschen römischen zahl ergibt sich doch aus der beschreibung, wie sich eine römische zahl zusammensetzt. also wenn einer für ne 4 IIII eingibt, ist das keine römische zahl -> diese soll dann eben in ein IV umgewandelt werden. oder eben das bsp mit der 99. die 99 wird nicht als IC (eins vor 100) dargestellt, sondern als XCIX (10 vor hundert + 1 vor 10 -> 100-10+10-1 quasi ^^). dann soll eben das falsche IC in ein richtiges XCIX umgewandelt werden. vom verständnis her nicht so schwer, das umzusetzen...

4.) Und was kann ich mir dann unter der Anmerkung nach Punkt 5 vorstellen? Eine römische Zahl wird ja immer als Zeichenkette ein-/angegeben?! Das Gegenteil ist ja dann ein dezimaler int?! Und wieso soll da dann plötzlich eine "falsche" Zeichenkette nicht fehlerbereinigt werden?
hmm, hier weis ich grad nich so recht, wass du meinst ^^

aber generell glaube ich, will er hier was ganz anderes, als ich erst gedacht hab (un du vllt auch). wie es scheint, sollst du eine klasse bauen, die EINE zahl repräsentiert. von operationen wie addition seh ich da grad garnix auf anhieb. sprich, du müsstest eine klasse bauen, die einmal einen string und einmal einen int wert enthält sowie 3 konstruktoren -> einmal der default konstruktor (hier müsste dann "n. a." und 0 gespeichert werden, dann einmal ein konstruktor, der aus nem string das objekt erzeugt (also aus der römischen zahl ne dezimale macht - am besten per methode - und nebenbei noch die römische zahl ggf korrigiert) und zu guter letzt noch einen, der das objekt aus ner dezimalen zahl erstellt (also aus der zahl den string für die römische zahl erstellt und die zahl an sich einfach so speichert).

die ermittlung des numerischen wertes is ja dann schon geschehen - einfach den int wert ausgeben. die weitere frage bleibt natürlich, was ne normalisiert römische zahl sein soll ^^


vielleicht kommt ja als nächster schritt dann sowas, wie eigene operatoren entwickeln (hab ich selbst auch noch nie gemacht). wenn mans grundprinzip kennt, dürfte das aber auch wieder simpel sein: man erstellt einfach ein neues objekt der klasse das mit dem ergebnis der numerischen teile gebildet wird. wenn ich jetz konkret wüsste, wie das funzt, würd ich nen bsp liefern ^^
 
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Na du liest halt meinetwegen ne römische 5 und ne römische 4 ein -> "V" und "IV". da haste schon deine römischen zahlen. die additions methode würde dann szs so aussehen:
string RomanNumber::addition(string a, string b) { ... }
am ende kommt wieder ein string bei raus -> V + IV = IX.
Wie Rechenmethoden zu schreiben wären, könnte ich mir schon vorstellen. Meine Frage ist eher, ob man überhaupt welche braucht ... oder ob da ganz was anderes gemeint ist ...

Was ist mit dem Satz gemeint: Erzeugung von römischen Zahlen [...] aus anderen römischen Zahlen. --> ??? Da hätte ich spontan auf Rechenmethoden getippt?!
aber generell glaube ich, will er hier was ganz anderes, als ich erst gedacht hab (un du vllt auch). wie es scheint, sollst du eine klasse bauen, die EINE zahl repräsentiert. von operationen wie addition seh ich da grad garnix auf anhieb. sprich, du müsstest eine klasse bauen, die einmal einen string und einmal einen int wert enthält sowie 3 konstruktoren -> einmal der default konstruktor (hier müsste dann "n. a." und 0 gespeichert werden, dann einmal ein konstruktor, der aus nem string das objekt erzeugt (also aus der römischen zahl ne dezimale macht - am besten per methode - und nebenbei noch die römische zahl ggf korrigiert) und zu guter letzt noch einen, der das objekt aus ner dezimalen zahl erstellt (also aus der zahl den string für die römische zahl erstellt und die zahl an sich einfach so speichert).
Ich schaue mal, wie weit ich das hinkriege. Mit Konstruktoren beschäftige ich mich seit ziemlich genau 2 Wochen ...
 
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

So, mit ein Bisschen googeln habe ich jetzt mal folgendes für den Anfang zusammengebastelt:
Code:
public class RomanNumber {
    
    static String romanNum;
    static int decimalNum;
    static char convertToDecimal;
    
    [COLOR=royalblue]/**
     * @return calculated decimal decimalNum of a specific Roman number
     */[/COLOR]
    public int convertToDecimal() {  
        char lastChar=' ';
                
        for (int i=romanNum.length()-1; i>=0; i--) {
            switch (romanNum.charAt(i)) {
                case 'I':
                    if (lastChar=='X' || lastChar=='V') {
                        decimalNum-=1;
                    } else {
                        decimalNum+=1;
                    }
                    break;
                case 'V':
                    decimalNum+=5;
                    break;
                case 'X':
                    if (lastChar=='C' || lastChar=='L') {
                        decimalNum-=10;
                    } else {
                        decimalNum+=10;
                    }
                    break;
                case 'L':
                    decimalNum+=50;
                    break;
                case 'C':
                    if (lastChar=='M' || lastChar=='D') {
                        decimalNum-=100;
                    } else {
                        decimalNum+=100;
                    }
                    break;
                case 'D':
                    decimalNum+=500;
                    break;
                case 'M':
                    decimalNum+=1000;
                    break;
                }
                lastChar=romanNum.charAt(i);
            }

            
        return decimalNum;    
    }

}
Testen kann ich's aber leider nicht, weil's JUnit TestCase nicht so geht, wie ich mir das vorstelle:
Code:
import static org.junit.Assert.assertEquals;

import org.junit.Test;


public class RomanNumberTest {
    
    private final String roman = "IV";
    
    @Test
    public void testConvertToDecimal() {
        assertEquals(roman.convertToDecimal(), 4);
    }
    
}
^^ Da sagt Eclipse: The method convertToDecimal() is undefined for the type String ???
 
Zuletzt bearbeitet:

DarkMo

Lötkolbengott/-göttin
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

ahso, ich glaub ich weis wieso. der erste code ist die roman klasse und die zweite die "main" die diese erste klasse aufruft?

in RomanNumber steht static char convertToDecimal; - und dann die methode public int convertToDecimal(). also das sollte an sich schon probleme geben *denk*, dass ne variable und ne methode gleich benannt sind (wobei ers vllt noch unterscheiden könnt anhand der klammer hinterm namen). jedenfalls rufst du in deiner 2. klasse roman.convertToDecimal() auf - ohne ein roman-objekt überaupt erstelt zu haben. er kann in diesem falle also NUR auf static elemente der klasse zugreifen -> und das ist die char variable, welche du mit nem string penetrierst ^^ also zumindest vom grundkonzept her - was dieses assertEquals sein soll, weis ich grad nich so recht.

ok, JETZT hab ichs grad gesehn ^^ roman ist bei dir ja ein string, und für die klasse string ist keine methode convertToDecimal() festgelegt worden. du hast also tatsächlich ein roman-objekt, allerdings ist das eben vom typ string und nicht vom typ RomanNumber - deine klasse wird also garnich verwendet.

und konstruktoren sind ganz einfach:
die "bauen" - konstruieren eben - das objekt bei der erzeugung -> RomanNumber roman; du erzeugst hier die variable roman vom typ RomanNumber. Jetzt werden speicherbereiche für die ganzen variablen erstellt, die zur klasse gehören - also hier eben romanNum, decimalNum und convertToDecimal (wozu auch immer du die hast ^^) - und das wars im groben mit dem standardkonstruktor (also auch wenn du selber keinen definierst, wird IMMER ein standard konstruktor bemüht - der kann halt nich sehr viel). in java wird alles glaube noch mit "0" initialisiert, das fehlt in c (wenn ichs richtig in erinnerung hab) zum bsp komplett - da steht also im zweifelsfall dann müll in der variablen ^^ der konstruktor hilft hier eben, das alles so zu initialisieren, wie man sich das wünscht. der konstruktor ist dabei eine methode, die einfach dem klassennamen entspricht:
RomanNumber() {}

damit haste schon deinen eigenen konstruktor gebaut - der ganusoviel kann, wie der default konstruktor :P in unserem falle müsste der default konstruktor romanNum mit "n. a." und decimalNum mit 0 initialisieren - und fertig. da wir aber auch noch ein RomanNumber-objekt mit nem string oder nem int direkt erzeugen können wollen, sollten wir den noch überladen (überladen bedeuted, dass man die selbe funktion/methode (vom namen her) mehrfach definiert - sie müsen sich dann in der parameter liste unterscheiden):
RomanNumber(int dNum) {}
RomanNumber(string rNum) {}

bei den beiden wirds dann halt schon schwieriger. der übergebene teil wird einfach weiter gereicht (also this.decimalNum = dNum usw) und den anderen Teil muss man dann aus dem übergebenen generieren. ganz rudimentär kann man die 3 kontruktoren erstmal so definieren *denk* (weis jetz nich, inwiefern das java kompatibel is, geht mir eher ums prinzip ^^):
Code:
RomanNumber() {
    this.romanNum = "n. a.";
    this.decimalNum = 0;
}

RomanNumber(string rNum) {
    this.romanNum = rNum;
    this.convertToDecimal();
}

RomanNumber(int dNum) {
    this.decimalNum = dNum;
    this.convertToRoman();
}

elegant gelöst und das problem auf später verschoben xD natürlich müssten zumindest die funktionsrümpfe der convertfunken existieren, damits wenigstens läuft. jetzt könnte man also schonmal RomanNumber roman = new RomanNumber("IV"); schreiben, und ein roman-objekt mit der entsprechung der römischen 4 erstellen. die convertfunktionen wären dann das nächste problem. ne rückgabe brauchst du eigentlich nicht - aber du kannst ja gern wieder überladen und ne 2. erstellen, die nen wert übernimmt und einen zurückgibt. das als static deklariert, und du kannst diese umwandlung auch extern nutzen, ohne ein RomanNumber-objekt erstellen zu müssen. also als bsp sowas hier:
Code:
private void convertToDecimal() {
    this.decimalNum = this.convertToDecimal(this.romanNum);
}

static int convertToDecimal(string rNum) {
    // umwandlungscode
    // ...
}

hat den vorteil, dass du dann immer nur den code der static funktion ändern musst. würdest du den code in beiden methoden direkt schreiben, müsstest du bei änderungen beide anpassen - das soll ja nich sinn und zweck sein ^^ wie du siehst, wieder elegant gelöst - und dennoch keinen schritt weiter gekommen xD
 
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Ok, danke erstmal!

Die Standarddinge, was Overloading ist und was Konstruktoren überhaupt sind, weiß ich eh. Im Moment sieht der Code so aus:
Code:
public class RomanNumber {
    
    private String romanNum;
    private int decimalNum;
    
    RomanNumber() {
        this.romanNum = "n. a.";
        this.decimalNum = 0;
    }

    RomanNumber(String rNum) {
        this.romanNum = rNum;
        this.convertToDecimal();
    }

    RomanNumber(int dNum) {
        this.decimalNum = dNum;
        this.convertToRoman();
    }
        
    /**
     * @return calculated decimal value of a specific Roman number
     */
    public int convertToDecimal() {  
        char lastChar=' ';
                
        for (int i=romanNum.length()-1; i>=0; i--) {
            switch (romanNum.charAt(i)) {
                case 'I':
                    if (lastChar=='X' || lastChar=='V') {
                        decimalNum-=1;
                    } else {
                        decimalNum+=1;
                    }
                    break;
                case 'V':
                    decimalNum+=5;
                    break;
                case 'X':
                    if (lastChar=='C' || lastChar=='L') {
                        decimalNum-=10;
                    } else {
                        decimalNum+=10;
                    }
                    break;
                case 'L':
                    decimalNum+=50;
                    break;
                case 'C':
                    if (lastChar=='M' || lastChar=='D') {
                        decimalNum-=100;
                    } else {
                        decimalNum+=100;
                    }
                    break;
                case 'D':
                    decimalNum+=500;
                    break;
                case 'M':
                    decimalNum+=1000;
                    break;
                }
                lastChar=romanNum.charAt(i);
            }

            
        return decimalNum;    
    }
    
    public void convertToRoman() {
        
    }

}
^^ Was ich noch gar nicht verstehe, ist, wann ich welches Attribut nehmen kann (final, static, privat, ...). Ich habe jetzt mal die Konstanten ganz oben auf nur private geändert. Das müsste ja erstmal heißen, dass die nur in dieser Klasse sichtbar sind, was eh so passen müsste?! final kann ich ja zumindest bei decimalNum nicht sagen, weil sich dessen Wert verändern können muss. Und wenn ich aber static sage, dann kommt in den Konstruktoren ein Warning: The static field RomanNumber.decimalNum should be accessed in a static way. static mag ich aber eh nicht und will ich möglichst vermeiden. ???

Und dann wäre da noch ein kleines Problemchen: Beim JUnit Test kommt raus, dass der sich "8" erwartet, als Ergebnis! Das verstehe ich überhaupt nicht, wenn ich mir den Code in der RomanNumber Klasse anschaue. Er sieht als erstes (von rechts beginnend) bei "IV" das "V" und rechnet 0+5=5. Dann geht er um eins nach links und sieht das "I". Dabei stellt er im Switch aber auch gleich fest, dass er rechts neben dem "I" ein "V" hat und rechnet daher 5-1=4 ... wieso erwartet sich der Test für "IV" also bitte "8"? :huh:
Code:
import static org.junit.Assert.assertEquals;

import org.junit.Test;


public class RomanNumberTest {
    
    @Test
    public void testConvertToDecimal() {
        RomanNumber roman = new RomanNumber("IV");
        assertEquals(4, roman.convertToDecimal());
    }
    
}
Mit assertEquals kannst du BTW verschiedene Werte des gleichen Datentyps miteinander vergleichen. Z.B. 2 ints, so wie ich das hier vorhabe. Dabei ist der erste/linke Wert der erwartete und der zweite/rechte der eigentliche.

[EDIT]
Gerade gesehen: Bei "V" kommt er auch nicht auf "5", sondern auf "10"! Wieso kommt der immer auf's doppelte?
 

DarkMo

Lötkolbengott/-göttin
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

wegen public und final und was weis ich: beschränk dich (sofern du e nicht unbedingt brauchst) erstmal nur auf public und private. das ist noch recht simpel: public heisst, man kann von aussen direkt auf die variable zugreifen und private bedeuted, dass es nur aus der klasse selbst geändert werden kann. deine klasse hier is dafür sogar nen super bsp:

du hast hier 2 klassen-variablen, die eng miteinander verknüpft sind: roman und decimal teil. beide stellen die selbe zahl dar, nur in unterschiedlichen "systemen". würdest du die public machen, könnte man von aussen (also aus ner aufrufenden funktion/main...) einen der beiden werte ändern und würde den sinn zerstören -> also aus ner 4/IV ne 5/IV machen. aber 5 und IV sind nich mehr das selbe, alles im eimer *ausm fenster hüpf* ^^ mit private verhindert man das geschickt, da ein
Code:
RomanNumber rn = new RomanNumber(4);
rn.decimalNum = 5;
nicht mehr funktioniert. man muss hierfür dann halt "schnittstellen" bereitstellen. damit is ganz simpel ne methode zur manipulation gemeint. gern auch als getter oder setter bezeichnet glaube, weil man eben gern die namenskonvention getDecimalNum() oder eben setRomanNum(newRomanNum) usw nutzt. get returned einfach den wert, set überschreibts mit den übergebenen neuen wert. und bei der set kann man dann eben beide teile hier in einer weise ändern, dass die konsitenz(?) der klasse gewahrt bleibt. also private = zugriff nur mittels this.

static... der meckert warscheinlich, weil du statt this eher den klassen namen nehmen sollst. also statt this.convertToDecimal(this.romanNum); eben RomanNumber.convertToDecimal(this.romanNum);. static sorgt halt dafür, dass man diese methoden nutzen kann, ohne ein klassenobjekt erzeugen zu müssen. wird zum bsp gerade bei so math-klassen gern verwendet. math.sqrt(2); als bsp. hier wärs äusserst ätzend jedesmal erst nen mathe-objekt erschaffen zu müssen.

protected kenn ich noch vom namen her, das wars aber auch schon ^^ war glaube irgendwas wegen vererbung. aber da müsst ich jetz selber nachlesen. und final hab ich jetz auch nur schonmal von gehört. bedeutede das, dass man die bei ner vererbung in der subklasse nich überschreiben musste? abstract musste man ja zwangsläufig überschreiben. ach naja, da hörts bei mir auch auf ^^

ps: falls ich groben unfug schreib, könnt ihr mich gern berichtigen ^^
 

Supeq

Software-Overclocker(in)
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

3.) Ermittlung der normalisierten Form bezieht sich dann wohl auf die Punkte 4 und 5?! Eine "falsche" römische Zahl gemäß den Regeln in Punkt 4 und 5 korrigieren?! Nur, wie das umsetzen? Das wird ja eine Raterei, welche römische Zahl der User gemeint haben könnte?!

4.) Und was kann ich mir dann unter der Anmerkung nach Punkt 5 vorstellen? Eine römische Zahl wird ja immer als Zeichenkette ein-/angegeben?! Das Gegenteil ist ja dann ein dezimaler int?! Und wieso soll da dann plötzlich eine "falsche" Zeichenkette nicht fehlerbereinigt werden?

^^ Blickt bei der Aufgabe irgendwer durch? :huh:

Vielen Dank für baldige Antworten!

ich springe einfach mal rein ;)

3) Ich würde hierfür einfach eine Methode "format_roman(string input_roman)" oder so ähnlich schreiben, die halt eine "römische Zahl" (auch in falscher Formatierung entgegennimmt), sie zunächst mit Hilfe deiner convertToDecimal() umwandelt, um sie dann mit convertToRoman wieder zurückzuwandeln und zurückzugeben.

Beispiel:

Eingabe: CCCCC
convertToDecimal(CCCCC) = 500
convertToRoman(500) = M

Ist eigentlich simpel, tricky wird es dann wenn mit der Subtraktionsregeln interpretiert werden soll. Da kann man dann wie du schon sagtest "raten welche römische Zahl gemeint ist" oder (mein Vorschlag) bei einer ungültigen Zahl (bsp.: IC) einfach eine Fehlermeldung ausgeben.
 
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Als erstes würde ich mal gerne wissen, wieso ich immer genau das doppelte zurückbekomme :huh: Für M 2000, für IV 8, ... ???

Bis mir das wer verraten kann, bastle ich jetzt mal eine convertToRoman Methode ...

[EDIT]
Codemäßig wäre ich wieder weiter, aber irgendwie funktioniert das alles nicht so, wie's soll ... :(
Code:
public class RomanNumber {
    
    private String romanNum;
    private int decimalNum;
    
    [COLOR=royalblue]/**
     * Constructor
     * used if there's no display of a Roman number
     * or it's decimal value is 0
     */[/COLOR]
    RomanNumber() {
        this.romanNum = "n. a.";
        this.decimalNum = 0;
    }
    
    [COLOR=royalblue]/**
     * Constructor
     * used for the decimal representation of a Roman number
     * @param rNum is any Roman number
     */[/COLOR]
    RomanNumber(String rNum) {
        this.romanNum = rNum;
        this.convertToDecimal();
    }
    
 [COLOR=royalblue]   /**
     * Constructor
     * used for the Roman representation of a decimal integer
     * @param dNum is any integer number
     */[/COLOR]
    RomanNumber(int dNum) {
        this.decimalNum = dNum;
        this.convertToRoman();
    }
        
   [COLOR=royalblue] /**
     * @return calculated decimal value of a specific Roman number
     */[/COLOR]
    public int convertToDecimal() {  
        char lastChar=' ';
                
        for (int i=romanNum.length()-1; i>=0; i--) { [COLOR=seagreen]// begin at the right end of the string (= Roman number)[/COLOR]
            switch (romanNum.toUpperCase().charAt(i)) {[COLOR=seagreen] // check the char on each position[/COLOR]
                case 'I':
                    if (lastChar=='X' || lastChar=='V') {
                        decimalNum-=1;
                    } else {
                        decimalNum+=1;
                    }
                    break;
                case 'V':
                    decimalNum+=5;
                    break;
                case 'X':
                    if (lastChar=='C' || lastChar=='L') {
                        decimalNum-=10;
                    } else {
                        decimalNum+=10;
                    }
                    break;
                case 'L':
                    decimalNum+=50;
                    break;
                case 'C':
                    if (lastChar=='M' || lastChar=='D') {
                        decimalNum-=100;
                    } else {
                        decimalNum+=100;
                    }
                    break;
                case 'D':
                    decimalNum+=500;
                    break;
                case 'M':
                    decimalNum+=1000;
                    break;
                }
                lastChar=romanNum.charAt(i); [COLOR=seagreen]// after each round, make current index of the string to position of last char[/COLOR]
            }

            
        return decimalNum;    
    }
    
[COLOR=royalblue]    /**
     * @return calculated Roman number of a decimal integer
     */[/COLOR]
    public String convertToRoman() {        
        String roman="";
        int value=decimalNum;
        
        if (value==0) {
            return romanNum; [COLOR=seagreen]// in this case "n. a."[/COLOR]
        }

        if (value>=0) {
            while (value/1000 >= 1) { [COLOR=seagreen]// while division by 1000 is possible, do so[/COLOR]
                roman+="M";
                value-=1000;
            }
            if (value/900 >= 1) { [COLOR=seagreen]// if division by 1000 is no longer possible, continue with the next smaller integer[/COLOR]
                roman+="CM";
                value-=900;
            }
            if (value/500 >= 1) {
                roman+="D";
                value = value - 500;
            }
            if (value/400 >= 1) {
                roman+="CD";
                value-=400;
            }
            while (value/100 >= 1) { [COLOR=seagreen]// while division by 100 is possible, do so[/COLOR]
                roman+="C";
                value-=100;
            }
            if (value/90 >= 1) { [COLOR=seagreen]// if division by 100 is no longer possible, continue with the next smaller integer[/COLOR]
                roman+="XC";
                value-=90;
            }
            if (value/50 >= 1) {
                roman+="L";
                value-=50;
            }
            if (value/40 >= 1) {
                roman+="XL";
                value-=40;
            }
            while (value/10 >= 1) { [COLOR=seagreen]// while division by 10 is possible, do so[/COLOR]
                roman+="X";
                value-=10;
            }
            if (value/9 >= 1) {[COLOR=seagreen] // if division by 10 is no longer possible, continue with the next smaller integer[/COLOR]
                roman+="IX";
                value-=9;
            }
            if (value/5 >= 1) {
                roman+="V";
                value-=5;
            }
            if (value/4 >= 1) {
                roman+="IV";
                value-=4;
            }
            while (value >= 1) {
                roman+="I";
                value-=1;
            }
        }
        
        return roman;
    }

}
^^ Das Problem mit den doppelten Werten habe ich immer noch und bei folgendem JUnit TestCase ...
Code:
import static org.junit.Assert.assertEquals;

import org.junit.Test;


public class RomanNumberTest {
    
    @Test
    public void testConvertToDecimal() {
        RomanNumber roman = new RomanNumber(0);
        assertEquals("n. a.", roman.convertToRoman());
    }
    
}
... kommt die Meldung: java.lang.AssertionError: expected:<n. a.> but was:<null>

Irgendwas passt da wohl mit dem Konstruktor nicht?!
 
Zuletzt bearbeitet:

Supeq

Software-Overclocker(in)
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Ich frag mich grad warum du die Methoden nicht Static machst, dann kannst du dir das ganze manuelle Instanzieren sparen und für spätere Anwendungen der Klasse ist es auch einfacher. Hier mal meine Version der convertToDecimal:

Code:
    // *Konstruktoren und Klassen-Variablen rausgeschmissen *


    public static int convertToDecimal(String romanNum) {  
        char lastChar=' ';
        int decimalNum = 0;
                
        for (int i=romanNum.length(); i>=1; i--) { // begin at the right end of the string (= Roman number)
            switch (romanNum.toUpperCase().charAt(i-1)) { // check the char on each position
                case 'I':
                    if (lastChar=='X' || lastChar=='V') {
                        decimalNum-=1;
                    } else {
                        decimalNum+=1;
                    }
                    break;
                case 'V':
                    decimalNum+=5;
                    break;
                case 'X':
                    if (lastChar=='C' || lastChar=='L') {
                        decimalNum-=10;
                    } else {
                        decimalNum+=10;
                    }
                    break;
                case 'L':
                    decimalNum+=50;
                    break;
                case 'C':
                    if (lastChar=='M' || lastChar=='D') {
                        decimalNum-=100;
                    } else {
                        decimalNum+=100;
                    }
                    break;
                case 'D':
                    decimalNum+=500;
                    break;
                case 'M':
                    decimalNum+=1000;
                    break;
                }
                lastChar=romanNum.charAt(i-1); // after each round, make current index of the string to position of last char
            }

            
        return decimalNum;    
    }

Läuft ^^

Deine doppelten Werte kommen übrigens daher, das du die Methode convertToRoman() zweimal aufrufst und zwar im Konstruktor und dann nochmal explizit (wobei die "decimalNum" zwischendurch nicht resetted wird)
 
Zuletzt bearbeitet:
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Moment mal ... habe gerade was rausgefunden: Selbst wenn ich meinen Code lasse (ohne deine Änderungen) kommt schon das richtige raus, wenn ich nur int decimalNum = 0; am Beginn der Methode einfüge!

Scheinbar stimmt meine Logik doch, nur initialisiert Java Variablen wohl nicht standardmäßig mit 0, wie ich ursprünglich dachte?! Wenn decimanlNum bereits irgendeinen Initialwert != 0 hat, ist klar, dass das dann mit den ganzen += und -= nie auf den richtigen Wert rauslaufen kann.

Ich hätte mir allerdings gedacht, dass die decimanlNum-Konstanten verwendet werden würde. Jetzt wird ein gleichnamiger int verwendet. Irgendwie habe ich hier das Gefühl, zu viele Sachen anzulegen?! Jetzt sind ja bald die Konstruktoren/Konstanten umsonst?! :huh:
BTW: Wenn ich die Methoden static mache, dann kommt beim Aufruf in den Konstruktoren: The static method convertToDecimal() from the type RomanNumber should be accessed in a static way
Und bei den Aufrufen der Konstanten kommt: Cannot make a static reference to the non-static field romanNum. Change modifier of 'romanNum' to static.

^^ Drum sag ich ja, ich mag static überhaupt nicht. Da kommen nur immer irgendwelche Probleme. Zumindest, wenn man noch nicht richtig weiß/versteht, wie das in der gesamten Klasse anzuwenden ist ... :huh:
 

Supeq

Software-Overclocker(in)
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Hab meinen vorigen Beitrag nochmal editiert, da steht warum es zu doppelten Werten kam^^
 
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Ja, aber macht das dann nicht wirklich die Konstruktoren überflüssig? BTW meinst du mit dem zweiten expliziten Aufruf den in der TestKlasse, oder?
 

Supeq

Software-Overclocker(in)
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Diesen "assertEquals("n. a.", roman.convertToRoman());" Aufruf meinte ich damit.

Wenn du nur statische Mehtoden in deiner Klasse verwendest dann ist ein Konstruktor überflüssig, weil du ja die Methoden aufrufen kannst ohne vorher ein Objekt zu instanzieren. Das ist ja grad das, was statische Mehtoden ausmachen. Schau dir mal die Java-Basicklassen , bspw. Math (Math (Java Platform SE 6)) an, dort sind auch alle Methoden statisch.
 
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Ok ... ich habe aber stark den Verdacht, dass die Aufgabe mit Konstruktoren gelöst werden sollte, wie auch DarkMo das angenommen hat. Insofern spare ich mir lieber das static.

Mir kommt nur immer noch das hier irgendwie "sinnlos" vor: int decimalNum=0; ???
decimalNum gäb's ja schon als Konstante. Das jetzt trotzdem noch mal als int anlegen?! Kann man das nicht "eleganter" lösen, dass es trotzdem mit 0 initialisiert bleibt und ich keine doppelten Werte bekomme?
Und bei der convertToRoman Methode habe ich das Problem, dass die TestKlasse meint:
java.lang.NullPointerException
at RomanNumber.convertToDecimal(RomanNumber.java:48)
at RomanNumberTest.testConvertToRoman(RomanNumberTest.java:17)
 

Supeq

Software-Overclocker(in)
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Also in deiner Aufgabenstellung steht nix davon, das man Konstruktoren verwenden muss. Aber okay , geht ja auch ohne static^^

Mir fällt jetzt spontan keine elegantere Lösung als Static-Methoden ein um deine Zählvariable (decimalNum) zurückzusetzen.

Unelegant finde ich es aber auch nicht, die Variable "per Hand" wieder auf 0 zu setzen. An irgendeiner Stelle musst du das ja definieren, woher soll dein Programm sonst wissen das die Variable nicht noch weiter verwendet wird.
Du könntest natürlich den Aufruf der Methode im Konstruktor entfernen(da hat die eigtl. sowieso nix zu suchen), aber ich dreh mich hier im Kreis weil static-Methoden die logische und offensichtliche Lösung für derartige Probleme sind.

decimalNum gäb's ja schon als Konstante.

Was meinst du mit Konstante? Das is doch ne Variable :huh:
 
Zuletzt bearbeitet:
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Ich bin gerade stark am Überlegen, ob's nicht am schlauesten/elegantesten wäre, noch wenigstens eine getRoman() Methode zu machen, so wie DarkMo das auch schon vorgeschlagen hat. Vielleicht muss ich mir dann nicht so viele Gedanken um (Doppel)Initialisierungen machen?! Mal schauen, worauf ich da noch komme ...

[EDIT]
Alle Fehler beseitigt! :-)
So funktioniert jetzt erst mal alles (zumindest gültige Umwandlungen):
Code:
public class RomanNumber {
    
    private String romanNum;
    private int decimalNum;
    
    [COLOR=royalblue]/**
     * Constructor
     * used if there's no display of a Roman number
     * or it's decimal value is 0
     */[/COLOR]
    RomanNumber() {
        this.romanNum = "n. a.";
        this.decimalNum = 0;
    }
    
    [COLOR=royalblue]/**
     * Constructor
     * used for the decimal representation of a Roman number
     * @param rNum is any Roman number
     */[/COLOR]
    RomanNumber(String rNum) {
        this.romanNum = rNum;
        this.convertToDecimal();
    }
    
    [COLOR=royalblue]/**
     * Constructor
     * used for the Roman representation of a decimal integer
     * @param dNum is any integer number
     */[/COLOR]
    RomanNumber(int dNum) {
        this.decimalNum = dNum;
        this.convertToRoman();
    }
        
   [COLOR=royalblue] /**
     * @return calculated decimal value of a specific Roman number
     */[/COLOR]
    public int convertToDecimal() {  
        char lastChar=' ';
        int decimalNum=0;
                
        for (int i=romanNum.length()-1; i>=0; i--) { [COLOR=seagreen]// begin at the right end of the string (= Roman number)[/COLOR]
            switch (romanNum.toUpperCase().charAt(i)) { [COLOR=seagreen]// check the char on each position[/COLOR]
                case 'I':
                    if (lastChar=='X' || lastChar=='V') {
                        decimalNum-=1;
                    } else {
                        decimalNum+=1;
                    }
                    break;
                case 'V':
                    decimalNum+=5;
                    break;
                case 'X':
                    if (lastChar=='C' || lastChar=='L') {
                        decimalNum-=10;
                    } else {
                        decimalNum+=10;
                    }
                    break;
                case 'L':
                    decimalNum+=50;
                    break;
                case 'C':
                    if (lastChar=='M' || lastChar=='D') {
                        decimalNum-=100;
                    } else {
                        decimalNum+=100;
                    }
                    break;
                case 'D':
                    decimalNum+=500;
                    break;
                case 'M':
                    decimalNum+=1000;
                    break;
                }
                lastChar=romanNum.charAt(i); [COLOR=seagreen]// after each round, make current index of the string to position of last char[/COLOR]
            }

            
        return decimalNum;    
    }
    
    [COLOR=royalblue]/**
     * @return calculated Roman number of a decimal integer
     */[/COLOR]
    public String convertToRoman() {        
        String roman="";
        int value=decimalNum;
        
        if (value==0) {
            return romanNum; [COLOR=seagreen]// in this case "n. a."[/COLOR]
        }

        if (value>=0) {
            while (value/1000 >= 1) { [COLOR=seagreen]// while division by 1000 is possible, do so[/COLOR]
                roman+="M";
                value-=1000;
            }
            if (value/900 >= 1) { [COLOR=seagreen]// if division by 1000 is no longer possible, continue with the next smaller integer[/COLOR]
                roman+="CM";
                value-=900;
            }
            if (value/500 >= 1) {
                roman+="D";
                value = value - 500;
            } 
            if (value/400 >= 1) {
                roman+="CD";
                value-=400;
            }
            while (value/100 >= 1) { [COLOR=seagreen]// while division by 100 is possible, do so[/COLOR]
                roman+="C";
                value-=100;
            }
            if (value/90 >= 1) { [COLOR=seagreen]// if division by 100 is no longer possible, continue with the next smaller integer[/COLOR]
                roman+="XC";
                value-=90;
            }
            if (value/50 >= 1) {
                roman+="L";
                value-=50;
            }
            if (value/40 >= 1) {
                roman+="XL";
                value-=40;
            }
            while (value/10 >= 1) { [COLOR=seagreen]// while division by 10 is possible, do so[/COLOR]
                roman+="X";
                value-=10;
            }
            if (value/9 >= 1) { [COLOR=seagreen]// if division by 10 is no longer possible, continue with the next smaller integer[/COLOR]
                roman+="IX";
                value-=9;
            }
            if (value/5 >= 1) {
                roman+="V";
                value-=5;
            }
            if (value/4 >= 1) {
                roman+="IV";
                value-=4;
            }
            while (value >= 1) {
                roman+="I";
                value-=1;
            }
        }
        
        return roman;
    }

}
Code:
import static org.junit.Assert.assertEquals;

import org.junit.Test;


public class RomanNumberTest {
    
    @Test
    public void testConvertToDecimal() {
        RomanNumber roman = new RomanNumber("MCDXXVI");
        assertEquals(1426, roman.convertToDecimal());
    }
    
    @Test
    public void testConvertToRoman() {
        RomanNumber roman = new RomanNumber(1426);
        assertEquals("MCDXXVI", roman.convertToRoman());
    }
    
}
Nur sowas hier geht noch nicht. Das muss ich noch ändern:
java.lang.AssertionError: expected:<n. a.> but was:<null>
Code:
    @Test
    public void testConvertToRoman() {
        RomanNumber roman = new RomanNumber(0);
        assertEquals("n. a.", roman.convertToRoman());
    }
^^ Nur wie?

Muss ich da irgendwie der entsprechenden Methode sagen, dass sie in dem Fall auf den ersten Konrtuktor zugreifen soll?! Definiert hätten wir den Fall darin ja schon ...
 
Zuletzt bearbeitet:

Supeq

Software-Overclocker(in)
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Der erste Konstruktor wird nur aufgerufen wenn du nichts übergibst ;) Das steht in deinem Kommentar auch falsch ^^( "or it's decimal value is 0")

Ich würd den ersten Konstruktor löschen und dafür in der converToRoman folgendes ändern:

Code:
 if (value==0) {
            return romanNum; // in this case "n. a."
        }

zu

Code:
 if (value==0) {
            return "n. a."; // in this case "n. a."
        }

Dann hast du´s^^
 
Zuletzt bearbeitet:
TE
TE
B

boss3D

Guest
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Ja, das ist schon klar, dass der nur dann aufgerufen wird, aber ich übergebe ja eh nichts, oder? Wo denn?

Wie man's sonst lösen könnte, weiß ich, aber ich hätte es halt gerne über den/die Konstruktor(en) gelöst. Wozu habe ich die denn sonst gemacht? Ich hoffe, DarkMo sagt dazu nochmal was. War ja seine Idee und mich würd's rein vom Verständnis her interessieren. :)

BTW: Ich glaube, so, wie's mein Kommentar sagt, wäre der Konstruktor gedacht?! Nur "verwende" ich den dann nicht/falsch?!
 

Supeq

Software-Overclocker(in)
AW: [JAVA] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

RomanNumber roman = new RomanNumber(0);

Da übergibst du doch die 0^^ Deswegen wird Konstruktor eins nicht aufgerufen.

So wie im Kommentar gedacht kannst du den Konstruktor nicht aufrufen weil du versuchst zwei unterschiedliche Situationen in einen Konstruktor zu packen (kein Parameter / Parameter =0).
 
Oben Unten