# throw-Exception für negative und gerade Zahlen



## HibikiTaisuna (11. Nov 2012)

Hallo Community!

Wie man bereits im Titel lesen kann, benötige ich in einer Aufgabe eine throw-Exception die bei negativen und geraden Zahlen auftritt.

Bisher bin ich schon soweit, dass gerade Zahlen triggern. Allerdings wird bei negativen Zahlen ganz normal weitergearbeitet (auch wenn negativeZahl % 2 == -1 und nicht +1 ist)

[JAVA=28]
public Diamond(final int size)
{
	//Diamant der Größe size (wird von main an die Methode weitergegeben)
	//Abbruch über throw-Befehl (bei negativen & geraden Zahlen)
	//Der Diamant besteht aus "#" und hat die Maße von size. Hintergrund ist "."
	//Überschreibt den Rohdiamanten in diamond (Main-Methode)

	if(size % 2 == 1)
	{
		background = '.';
		diamond = '#';
		width = size;
		fields = width * width;
	}
	else
	{
		throw new IllegalArgumentException("muss ungerade, positive Zahl sein");
	}
}//Diamond(final int size)
[/code]

Kann man das ganze eigentlich auch ohne if/else lösen? PMD sagt mir, dass meine Cyclomatic Complexity bei 10 liegt. Sollte allerdings niedriger als 10 für die Abgabe sein. Andersweitig lässt sich die Komplexität leider nicht mehr verringern.

Wäre super wenn jemand weiß, wo das Problem liegt. Wir hatten an der Uni den throw-Befehl leider noch nicht so gut besprochen.

Falls Ihr noch mehr Infos benötigt einfach kurz nachfragen.

Vielen Dank bereits im Voraus für Eure Hilfe!

Viele Grüße
Stefan


----------



## pro2 (11. Nov 2012)

So toll kenne ich mich da auch nicht aus, aber generell prüft man glaube ich zuerst auf die Fehler. Das heißt eher so etwas wie das hier:


```
if((size < 0) || (size % 2 == 0))
{
    throw new Exception("...");
}
else
{
    ...
}
```

Negative fängst du ja einfach durch das kleiner 0 ab. Warte aber lieber noch auf andere Antworten


----------



## HibikiTaisuna (11. Nov 2012)

Die Lösung wäre jedenfalls nicht verkehrt. Einziges Problem wäre, dass


```
if((size < 0) || (size % 2 == 0))
```

eine weitere Cyclomatic Complexity hinzufügt und damit das Programm für die Abgabe zu komplex wird.

Mal sehen, ob es noch eine andere Lösung gibt, bei der ich ohne zusätzliches statement auskomme. 

Auf alle Fälle schon mal vielen Dank!


----------



## JCODA (11. Nov 2012)

HibikiTaisuna hat gesagt.:


> (auch wenn negativeZahl % 2 == -1 und nicht +1 ist)




Ja, das Modulo in Java ist immer >=0. 

Wenn die Exception geworfen wird, braucht man kein else, also mal so probieren: 


```
if((size < 0) || (size % 2 == 0))
{
    throw new Exception("...");
}
...
```


Wenn das nicht hilft, vielleicht mal mehr Code posten.


----------



## HibikiTaisuna (11. Nov 2012)

JCODA hat gesagt.:


> Ja, das Modulo in Java ist immer >=0.



Ich dachte, dass das Modulo auch negativ wird. Denn wenn ich folgenden Code ausführe kommt -1 raus:


```
public class Test
{
	public static void main(final String[] args)
	{
		int a = -3;
		int b = a % 2;
		System.out.println(b);
	}
}
```

EDIT: Beide Lösungen akzeptieren trotzdem noch negative Werte. Vielleicht liegt es auch an der Main-Methode des Professors 


```
/* (C) 2012, R. Schiedermeier, [email]rs@cs.hm.edu[/email]
 * Oracle Corporation Java 1.7.0_09, Linux i386 2.6.32.58
 * fiona (Intel Atom CPU N270/1600 MHz, 2 Cores, 2048 MB RAM)
 */
/** Anwendungsprogramm fuer Diamanten.
 * @author Reinhard Schiedermeier, [email]rs@cs.hm.edu[/email]
 * @version 2012-11-09
 */
public class DiamondMain {
    /** Hauptprogramm.
     * Liest die Kommandozeilenargumente und uebersetzt sie in verschiedene Operationen.
     * @param args Kommandozeilenargumente.
     * Eine Liste von:
     * + aktuellen Diamanten vergroessern,
     * - aktuellen Diamanten verkleinern,
     * = aktuellen Diamanten ausgeben,
     * Zahl = neuen aktuellen der angegebenen Groesse erstellen,
     *:x = Diamantenzeichen x neu festlegen,
     * sonst = Hintergrundzeichen neu festlegen.
     */
    public static void main(final String... args) {
        Diamond diamond = new Diamond();
        for(String arg: args)
            if("+".equals(arg))
                diamond.grow();
            else if("-".equals(arg))
                diamond.shrink();
            else if("=".equals(arg))
                diamond.print();
            else if(Character.isDigit(arg.charAt(0)))
                diamond = new Diamond(Integer.parseInt(arg));
            else if(arg.charAt(0) == ':')
                diamond.setDiamondChar(arg.charAt(1));
            else
                diamond.setBackgroundChar(arg.charAt(0));
    }

}
```


----------



## JCODA (11. Nov 2012)

HibikiTaisuna hat gesagt.:


> Ich dachte, dass das Modulo auch negativ wird. Denn wenn ich folgenden Code ausführe kommt -1 raus:



Okay, dann wars andersrum und in der Mathematik kann er nicht negativ werden. Ich sollte mehr :rtfm: lesen. ^^


----------



## HibikiTaisuna (11. Nov 2012)

Dann sollte der Code allerdings schon bei meiner ursprünglichen Lösung eine Exception für die negative Zahl auswerfen. Einzige Möglichkeit ist, dass der Wert aus der Kommandozeile falsch an die Methode weitergegeben wird.


----------



## Camill (11. Nov 2012)

http://pmd.sourceforge.net/pmd-4.2.5/rules/codesize.html hat gesagt.:
			
		

> Complexity is determined by the number of decision points in a method plus one for the method entry. The decision points are 'if', 'while', 'for', and 'case labels'. Generally, 1-4 is low complexity, 5-7 indicates moderate complexity, 8-10 is high complexity, and 11+ is very high complexity.


Liegt also sicherlich nicht an deinem Code.


----------



## HibikiTaisuna (11. Nov 2012)

Camill hat gesagt.:


> Liegt also sicherlich nicht an deinem Code.



Naja, war ja auch nur ein Codeausschnitt. Allerdings scheint der Upload-Server doch nicht wegen der Komplexität zu meckern. Vielleicht wurde die Complexity-Zahl manuell angehoben. Einzig die Exception stört...

Das wäre der gesamte Code meiner Klasse:


```
/*
Hochschule München, Fakultät 07 für Mathematik und Informatik
Praktikum Softwareentwicklung I, WS2012, Studiengruppe IF1A
Autor: Stefan
Datum: 11.11.2012
Entwicklungssystem: Windows 8 Professional 32-bit, JDK SE 7, Notepad++ v6.1.5
Aufgabe: Klasse I - Diamond
*/

public class Diamond
{
	//Objektvariablen erstellen
	char diamondCharacter;
	char background;
	int fields;
	int width;

    public Diamond()
    {
		//Diamant der Größe 1 mit Zeichen #
		//Erstellt sozusagen den "Rohdiamanten"
		//Füttert diamond in Main mit ersten Daten
		diamondCharacter = '#';
		width = 1;
		fields = 1;
	}

	public Diamond(final int size)
	{
		//Diamant der Größe size (wird von main an die Methode weitergegeben)
		//Abbruch über throw-Befehl (bei negativen und geraden Zahlen)
		//Der Diamant besteht aus "#" und hat die Maße von size. Hintergrund ist "."
		//Überschreibt den Rohdiamanten in diamond (Main-Methode)
		if(size % 2 < 1)
		{
			throw new IllegalArgumentException("muss ungerade, positive Zahl sein");
		}
		else
		{
			background = '.';
			diamondCharacter = '#';
			width = size;
			fields = width * width;
		}
	}

	public void grow()
	{
		//Lässt den Diamanten um zwei größer werden (links und rechts)
		width = width + 2;
		fields = width * width;
	}

	public void shrink()
	{
		//verkleinert den Diamanten um zwei (links und rechts -> nicht kleiner als 1)
		if(width > 1)
		{
			width = width - 2;
			fields = width * width;
		}
	}

	public void setDiamondChar(final char diamondChar)
	{
		//legt den Character-Baustein für den Diamanten fest
		diamondCharacter = diamondChar;
	}

	public void setBackgroundChar(final char backgroundChar)
	{
		//legt den Character-Baustein für den Hintergrund fest
		background = backgroundChar;
	}

	public void print()
	{
		//Gibt den erstellten Diamanten aus Diamond(final int size) oder Diamond() aus
		//Die Daten zum printen werden aus Main (Variable diamond) geholt
		int rowTrigger = 0;
		int rowDraw = 0;

		for(int fieldCounter = 0; fieldCounter < fields; fieldCounter += width) //Anzahl Felder
		{
			//Zeilen-Zähler
			if(rowTrigger <= width/2)
			{
				//nach oben counten um Berechnung für oberen Bereich zu ermöglichen
				rowDraw += 1;
				rowTrigger += 1;
			}
			else
			{
				//nach unten counten um Berechnung für unteren Bereich zu ermöglichen
				rowDraw -= 1;
			}
			//Wenn nur 1 Reihe, dann den Diamanten direkt ausgeben damit die for-Schleife erst gar nicht benötigt wird
			if(width == 1)
			{
				System.out.print(diamondCharacter);
				System.out.println();
			}
			//Wird ausgeführt, so lange es sich nicht um die mittlere Zeile handelt
			else if(rowDraw <= width/2)
			{
				//for-Schleife für die ersten Background-Zeichen
				for(int backgroundCounter = 0; backgroundCounter < (width/2) - (rowDraw - 1); backgroundCounter++)
				{
					System.out.print(background);
				}
				//for-Schleife für die Diamanten-Zeichen
				for(int diamondCounter = 0; diamondCounter < width - (width/2 - rowDraw + 1) * 2; diamondCounter++)
				{
					System.out.print(diamondCharacter);
				}
				//for-Schleife für die zweiten Background-Zeichen
				for(int backgroundCounter = 0; backgroundCounter < (width/2) - (rowDraw - 1); backgroundCounter++)
				{
					System.out.print(background);
				}
				System.out.println();
			}
			//gibt die mittlere Zeile aus in der nur Diamantencharacter sind
			else
			{
				//for-Schleife für die Diamanten-Ausgabe
				for(int diamondCounter = 0; diamondCounter < width; diamondCounter++)
				{
					System.out.print(diamondCharacter);
				}
				System.out.println();
			}
		}//for-Schleife fieldCounter
	}//Methode
}//class
```


----------



## Herd123 (12. Nov 2012)

1. hast du die falsche Exception...
[Java=36]throw new RuntimeException("Size must be odd and positiv!");[/code]
muss es da heißen....

und 2. wirst du das Programm dannach nicht hochbekommen, weil
du im Defaultkonstruktor nicht

[Java=22]background = '.';[/code]
festgelegt hast... 
Dann wird er dir bei der Eingabe java DiamondMain = + = nämlich keine Punkte dazu schmeißen.

Grüße vom ebenfalls Dummen, der hier eigentlich nur aus Zufall gelandet ist und ebenfalls in IF1A ist.

EDIT:
außerdem reißt der Schiedermeier dir den Schädel ab, wenn du die Objektvariablen net private setzt ;D


----------



## nillehammer (13. Nov 2012)

Herd123 hat gesagt.:
			
		

> 1. hast du die falsche Exception...
> 
> ```
> throw new RuntimeException("Size must be odd and positiv!");
> ...


Also, wenn das nicht durch die Musterlösung Eures Profs vorgegeben ist, würde ich dem gerne widersprechen. Die IlegalArgumentException aus dem ersten Post:

```
throw new IllegalArgumentException("muss ungerade, positive Zahl sein");
```
ist die bessere Wahl. Sie ist eine Subklasse von RuntimeException. Deswegen auch unchecked und beschreibt den Fehlerzustand besser, nämlich, dass ein Argument (size) aus irgend einem Grund illegal ist.


----------



## HibikiTaisuna (13. Nov 2012)

Mittlerweile weiß ich, warum die Exception nicht geworfen wird. Das isDigit in der Main-Methode erkennt keine negativen Zahlen. Dadurch wird bei Eingabe von beispielsweise -5 der else-Zweig von main ausgeführt und die 5 abgeschnitten. Der Background ist dann ein - .

Nach der gestrigen Vorlesung hab ich die Variablen nun auch private gesetzt und der Server akzeptiert die Lösung. Einzig der fehlende . als Standardbackground von Diamond() hatte eine Fehlermeldung ausgegeben.

Auf alle Fälle vielen Dank für Eure Hilfe!!!

PS. Immer, immer, immer private


----------



## Herd123 (14. Nov 2012)

Der Prof hats mit RuntimeException vorgemacht (ebenfalls ein Zahlenbespiel, dessen Parameter nicht 0 werden darf). Natürlich wäre die andere Variante passender. Ehrlich gesagt habe ich keinen Plan, wie der darauf reagiert, ich weiß nur, was er gemacht hat.

Außerdem nimmt seine Methode das "-" doch als Signal für die Methode shrink... Da das Ding chars einzeln ausliest, kannst du somit also keine negativen Zahlen eingeben... (oder täusche ich mich da...?)


----------

