# double auf Ganzzahligkeit prüfen?



## Guest (18. Jan 2009)

Hallo,

ich versuche im moment das Faktorisierungsverfahren nach Lehmann[1] zu implementieren. Nun stehe ich allerdings vor dem Problem das ich y=x²-4kn berechnen soll (n und k sind gegeben) und dann Prüfen soll ob y eine Quadratzahl ist. Ich habe mir dafür überelgt das ich aus y die Wurzel ziehe und dann gucke ob das Ergebnis Gannzzahlig ist. Da die Funktion Math.sqrt aber einen double zurück liefert steht ich nun vor dem Problem wie teste ich für eine Gleitkomma zahl ob sie ganzzahlig ist. Nach dem was ich einmal gelernt habe müsste ich dafür ja eigentlich nur die Mantisse(?) der Gleitkommazahl testen, aber wie mache ich das ohne dafür zu tief in die Trickkiste zu greifen? Aber vielleicht gibt es ja noch einen anderen Weg, den ich im moment nicht sehe.
Ich wäre über einen entsprechenden hinweis auf jeden Fall sehr dankbar.
Viele Grüsse
Dan



[1] http://de.wikipedia.org/wiki/Faktorisierungsmethode_von_Lehman


----------



## Ark (18. Jan 2009)

Probier mal das:

```
boolean xIstGanzzahl = (x % 1) == 0;
```
Ungetestet! Keine Garantie!

Ark


----------



## Ebenius (18. Jan 2009)

Ich würde so prüfen: 
	
	
	
	





```
double wurzel = Math.sqrt(y);
int pruefWert = (int) Math.round(wurzel * wurzel);
boolean yIstQuadratZahl = pruefwert == y;
```


----------



## SlaterB (18. Jan 2009)

hmm?

```
public class Test {

	public static void main(String[] args) {
		int y = 10;
		double wurzel = Math.sqrt(y);
		int pruefWert = (int) Math.round(wurzel * wurzel);
		boolean yIstQuadratZahl = pruefWert == y;
		System.out.println(yIstQuadratZahl);
	}

}
```


----------



## Ebenius (18. Jan 2009)

Heidenei, muss ich gesoffen haben...  Der Ansatz ist natürlich vollkommener Unsinn. 

Was ich eigentlich schreiben wollte: 
	
	
	
	





```
int wurzel = (int) Math.round(Math.sqrt(y));
int pruefWert = wurzel * wurzel;
boolean yIstQuadratZahl = pruefWert == y;
```

Ebenius

PS: Slater, wir sind jetzt quitt, oder? ;-)


----------



## SlaterB (18. Jan 2009)

wie auch immer


----------



## Triebi (18. Jan 2009)

Sind weitere Vorschläge erwünscht?

```
class Check {
public static void main(String[] a){
  double d1 = 1.0;
  double d2 = 2.2;
  System.out.println(d1 + " ganz? " + (d1 == (int)d1));
  System.out.println(d2 + " auch? " + (d2 == (int)d2));
 }
}
```


```
1.0 ganz? true
2.2 auch? false
```


----------



## Ebenius (18. Jan 2009)

Doubles nie auf Gleichheit prüfen! Deshalb hab ich ja einen anderen Vorschlag (den zweiten  ) gemacht.


----------



## Guest (18. Jan 2009)

Hallo,

ich habe mich direkt erschrocken was für eine Ressonanz ich mit dieser Frage erzielt habe. Auf jeden fall vielen dank für die vielen hilfreichen Antworten. Ich denke ich werde die Idee von Ebenius beherzigen und das so umsetzen.
Viele Grüsse
Dan


----------



## Triebi (18. Jan 2009)

Ebenius hat gesagt.:
			
		

> Doubles nie auf Gleichheit prüfen!


Ja, ich weiß, die Ungenauigkeit... :roll: 
Was ist mit
	
	
	
	





```
class Check {
public static void main(String[] a) {
  double d1 = 1.0;
  double d2 = 2.2;
  System.out.println(d1 + " ganz? " + (Double.compare((int)d1, d1) == 0));
  System.out.println(d2 + " auch? " + (Double.compare((int)d2, d2) == 0));
 }
}
```
Wenn Double#compare nicht weiß, wie richtig verglichen wird - wer dann?


----------



## Marco13 (18. Jan 2009)

Compare vergleicht intern auch auf Gleichheit (testet noch Sonderfälle wie NaN usw...).

double x = 0;
x+= 0.1;
x+= 0.1;
x+= 0.1;
x+= 0.1;
x+= 0.1;
Double.compare(0.5, x); // Gibt vtml. nicht 0

Um die Ungenauigkeit zu umgehen, muss man GROB sowas machen wie
boolean equals(double a, double b) { return Math.abs(a-b) < 1e-7; }
wobei man das "epsilon" eigentlich auch noch auf die Größe der beiden Zahlen beziehen muss (siehe Knuth TAOCP)


----------



## Ebenius (18. Jan 2009)

Triebi, das funktioniert ganz genauso wenig. Es geht ja nicht darum, dass falsch verglichen wird. Es geht darum, dass die zwei Doubles sich eben minimal unterscheiden können. Der richtige weg ist ein Epsilon-Vergleich. Da ich aber zu faul war, darüber nachzudenken, welches Epsilon hier passend wäre, hab ich mir was anderes ausgedacht, was IMHO sicher funktionieren sollte.

// EDIT: Marco, mit Deinem letzten Satz erklärst Du gut, warum ich lieber anders rangehen wollte. 

Ebenius


----------



## Marco13 (19. Jan 2009)

OK, dann hier nochmal der Link: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17


----------

