# Math.round



## mattrock (20. Mrz 2011)

Hi,
ich habe folgenden Code:


```
import java.util.ArrayList;
import a1.CartItem;

public class ShoppingCart {
	
	//Konstruktor= Initialisiert den Zustand eines neuen Objekts.
	public ShoppingCart(){
		myShoppingCart = new ArrayList<Object>(0);
	}
	
	//speichern
	ArrayList<Object> myShoppingCart;
	
	public void add(CartItem item){
		myShoppingCart.add(item);		
	}
		
	public double getTotalCost(){
		double total=0.0;
		for(int i=0;i<myShoppingCart.size();i++){
			CartItem test = (CartItem) myShoppingCart.get(i);
			total += test.pricePerUnit * test.quantity;
		}
		return total;
	}
	
	public String toString(){
		String _return = "";
		double totalcost=0;
		for(int i=0;i<myShoppingCart.size();i++){
			_return = _return+"  "+myShoppingCart.get(i)+"\n";
		}
		totalcost += getTotalCost();
		return  _return+"\nSumme:\t\t\t\t\t"+totalcost ;											
		
	}
			

}
```

Nun möchte ich das totalcost auf 2 Stellen hinter dem Komma gerundet wird. Es müsste 42,83 eigentlich raus kommen.
Aber wenn ich Math.round anwende kommt 42 raus. Warum??

```
totalcost += getTotalCost();
		return  _return+"\nSumme:\t\t\t\t\t"+Math.round(totalcost*100)/100 ;
```

Oder habe ich da einen großen Denkfehler

Dank schon mal im voraus.


----------



## Titanpharao (20. Mrz 2011)

Wieso rechnest du *100 und danach / 100 ? Würde nicht 

```
Math.round(totalcost);
```
 ausreichen?


----------



## mattrock (20. Mrz 2011)

dann rundet er auf 43 auf


----------



## Antoras (20. Mrz 2011)

Wenn du in Java eine Ganzzahl durch eine andere Ganzzahl teilst, dann kommt auch wieder eine Ganzzahl raus - selbst wenn das Ergebnis eine Fließkommazahl wäre. Caste eine Zahl vor der Berechnung in eine Fließkommazahl und du erhältst das richtige Ergebnis.

```
5/2 => 2
(float)5/2 => 2.5
```


----------



## Ralph-Uwe (20. Mrz 2011)

Moin,

versuche mal Deine Variabel totalcost mit 0.0 zu initialisieren.


```
double totalcost=0.0;
```


----------



## mattrock (20. Mrz 2011)

also 
	
	
	
	





```
double totalcost=0.0;
```
 klappt nicht. Da verändert sich rein gar nichts.

Wenn ich das Math.round weg lasse kommt Summe:	42.830000000000001 raus.
Will nur das nur 42,83 stehen bleibt. 

Irgendwie klappt das alles nicht. Auch nicht mit den casten.


----------



## tfa (20. Mrz 2011)

Teil mal durch "100." statt durch "100". Damit wird das Ergebnis auch eine Fließkommazahl und kein integer.


----------



## mattrock (20. Mrz 2011)

Ja klar. Hat funktioniert wenn ich durch 100.0 teile. Vielen Dank.
Man so was von einfach. Aber jetzt merke ich es mir.


----------



## tfa (20. Mrz 2011)

Wenn es dir nur um die formatierte Ausgabe geht, benutze lieber einen Formatter, z.B.


```
System.out.printf("%3.2f", totalcost)
```


----------



## Shulyn (21. Mrz 2011)

Du solltest beim Runden von Negativen Zahlen aufpassen. Math.round nimmt es da nicht so ganz genau.

[Java]
    public static void main(String[] args) {

        double a = 2.4;
        double aa = -2.4;

        double b = 2.5;
        double bb = -2.5;

        double c = 2.6;
        double cc = -2.6;

        System.out.println(" "+ a  + " =  " + Math.round(a));
        System.out.println("" + aa + " = " + Math.round(aa));
        System.out.println(" "+ b  + " =  " + Math.round(b));
        System.out.println("" + bb + " = " + Math.round(bb));
        System.out.println(" "+ c  + " =  " + Math.round(c));
        System.out.println("" + cc + " = " + Math.round(cc));
      }
[/Java]

[Java]
 2.4 =  2
-2.4 = -2
 2.5 =  3
-2.5 = -2   // falsch, im Negativen wird bei ",5" von der 0 weg gerundet.  -3 ist hier Richtig.
 2.6 =  3
-2.6 = -3
[/Java]


----------



## Ark (21. Mrz 2011)

Shulyn hat gesagt.:


> Du solltest beim Runden von Negativen Zahlen aufpassen. Math.round nimmt es da nicht so ganz genau.


Warum sollte das im Code Gezeigte ein Fehler sein? Es wurde doch völlig korrekt ab 0.5 aufgerundet, sprich: im Zweifelsfall hat die größere Zahl gewonnen, und -2 ist nun einmal größer als -2.5.

Ark


----------



## Shulyn (22. Mrz 2011)

Ark hat gesagt.:


> [..] Es wurde doch völlig korrekt ab 0.5 aufgerundet,[..]
> Ark


Ersetze aufrunden durch [von der 0 weg] und abrunden durch [zur 0 hin].

-x.0 / -x.1 / -x.2 / -x.3 / -x.4 abgerundet [zur 0 hin]  bei
-x.5 / -x.6 / -x.7 / -x.8 / -x.9 aufgerundet [von der 0 weg].

Oder anders ausgedrückt, wenn du das Vorzeichen ausklammerst, sollte das SELBE Ergebnis zu stande kommen.


----------



## xehpuk (22. Mrz 2011)

Shulyn hat gesagt.:


> Oder anders ausgedrückt, wenn du das Vorzeichen ausklammerst, sollte das SELBE Ergebnis zu stande kommen.


Das hat dann aber nichts mehr mit mathematisch korrektem Runden zu tun, sondern mit deinen eigenen Wünschen, welche du dann mit einer eigenen Methode verwirklichen müsstest.


----------



## SlaterB (22. Mrz 2011)

nana, nicht so feste mit dieser Bewertung, wo ist das bitte eindeutig definiert?
wieviele Menschen würden wohl (ohne die Definition gerade nachgelesen zu haben) so oder so entscheiden?
meiner spontanen Einschätzung nach ist die Java-Umsetzung auch eher ungewöhnlich,

Excel macht es z.B. andersherum, auch wenn das vielleicht nicht zählen muss,
genausowenig dann folgendes Dokument von Microsoft
How To Implement Custom Rounding Procedures


> Arithmetic Rounding
> When rounding always down or up, the resulting number is not necessarily the closest to the original number. For example, if you round 1.9 down to 1, the difference is a lot larger than if you round it up to 2. It is easy to see that numbers from 1.6 to 2.4 should be rounded to 2.
> 
> However, what about 1.5, which is equidistant between 1 and 2? By convention, the half-way number is rounded up.
> ...



edit:
auch Oracle-DB rundet symmetrisch


----------



## hansmueller (22. Mrz 2011)

Hallo,

wie Math.round() runden soll, kann man doch genau einstellen: RoundingMode (Java Platform SE 6)

MfG
hansmueller


----------



## Marco13 (22. Mrz 2011)

BigDecimal. Aber bei Math.round ist's fest.


----------



## SlaterB (22. Mrz 2011)

@hansmueller
nicht wirklich, denn die Implementierung ist

```
public static long round(double a) {
	return (long)floor(a + 0.5d);
    }
```

RoundingMode ist aber ein tolles Stichwort, was ich vorher schon selber gerade verkünden wollte,
wenn ich das nicht ganz falsch sehe, gibt es dort keine Möglichkeit, die asymmetrische Rundung durchzuführen!
symmetrisch ist HALF_UP, der Standard

damit stellt sich Math.round() gegen die ausgereifteren Klassen, auch wenn ich die programmatische Umsetzung sympatisch finde,
habe ich glaube ich auch irgendwo als Code stehen  (+0.5, dann floor)


----------



## Blakh (22. Mrz 2011)

@ SlaterB Vertauschst du da nicht asymmetrisch und symmetrisch? 



> You can implement rounding half-way numbers in a symmetric fashion, such that -.5 is rounded down to -1, or in an asymmetric fashion, where -.5 is rounded up to 0.



Die Asymetrische Rundung ist doch implementiert?! Oder versteh ich da was falsch gerade.


----------



## SlaterB (22. Mrz 2011)

inwiefern vertausche ich das? ich treffe ja viele Aussagen dazu, meiner Ansicht nach alles konsistent

asymmetrisch:
- Math.round()
- in RoundingMode nicht verfügbar
- mathematisch vielleicht sauberer, nach Menschenverstand aber eher unerwartet/ unhandlich

symmetrisch:
- Excel
- Oracle
- RoundingMode HALF_UP


----------



## Blakh (22. Mrz 2011)

Das mathematische Runden wird auch Symmetrisches Runden genannt. 

Ich habe den begriff asymmetrisch jetzt nicht direkt gefunden, aber meiner Meinung müsste das doch HALF_DOWN sein, wenn die Definition stimmt:



> or in an asymmetric fashion, where -.5 is rounded up to 0.


----------



## AmunRa (22. Mrz 2011)

Nach Wikipedia ist symetrisch runden weder fix nach oben noch fix nach unten, sondern es wird auf die nächste gerade Zahl gerundet.

z.b 

2.5 wird zu 2 und 3.5 wird zu 4
ebenfalls im negativen 

-2.5 wird zu -2 und -3.5 wird zu 4
Rundung ? Wikipedia


----------



## SlaterB (22. Mrz 2011)

ich beziehe mich auf den von mir zitierten Artikel, wenn es andere Definitionen für die Begriffe wie 'symmetrisch' gibt, dann ist das natürlich unglücklich

@Blakh
HALF_DOWN rundet im positiven Bereich 2.5 auf 2, ist also komplett was anderes
@AmunRa
dass .5 mal auf, mal abgerundet wird, ist zwar statisch praktisch aber ebenso relativ fern der Diskussion was anderes


----------



## Blakh (22. Mrz 2011)

Ich bin verwirrt. Nach deiner Definition ist asymmetrisch, wenn bei -.5 auf 0 gerundet wird.


Aber das macht doch genau derRoundingMode HALF_UP.

Edit. Ne macht er nicht .

Nochmal Edit: CEILING ist doch aber assymetrisch und FLOOR, genauso wie UP und DOWN. 

Versteh ich den Begriff assymetrisch hier falsch?


----------



## SlaterB (22. Mrz 2011)

es geht seit Shulyn vs xehpuk, wo ich mich einfach eingemischt habe, darum, ob -1.5 auf -1 oder -2 gerundet wird,
wie .6 bis .4 gerundet wird ist klar, .5 im positiven Bereich ebenso, nur .5 im Negativen fraglich,

CEILING, FLOOR, UP, DOWN, sind unerheblich, HALF_DOWN genauso (rundet .5 im postivien ab)
HALF_EVEN = abwechseln mal auf und mal abrunden ist für sich nett, aber zu kompliziert, rundet ja teils auch .5 im positiven Bereich ab

wenn -1.5 entweder auf -1 oder auf -2 gerundet wird, dann sind das genau zwei Varianten,
meine Benennung richtet sich nach meinem Zitat von 11:47, ist ja auch egal,
Math.round() macht es soundso, andersrum ist die Alternative


----------



## xehpuk (22. Mrz 2011)

Hmm, ich habe auch nicht gedacht, dass man da so viele "gängige" Verfahren hat.

Ich sehe zumindest das asymmetrische Runden per Math.round() als Standard in der Mathematik. Interessant finde ich auch die Bemerkung zu ROUND_HALF_UP im JavaDoc:

```
Note that this is the rounding mode that most of us were taught in grade school.
```
Ich kann mich nicht daran erinnern, dass uns damals explizit etwas zum Runden von negativen Dezimalbrüchen mitgeteilt wurde, was dann ja implizit für die Asymmetrie steht ("auf die nächstgrößere Zahl"). Aber das ist dann wohl auch von Staat zu Staat, von Land zu Land, von Schule zu Schule und von Lehrer zu Lehrer unterschiedlich. 

Per Google lässt sich auch nicht so einfach Fachliteratur dazu finden. Vielleicht frag ich meinen Mathe-Prof demnächst mal danach.


----------



## SlaterB (22. Mrz 2011)

.5 wird "auf die nächstgrößere Zahl" gerundet genau wie * 3 eine größere Zahl ergibt, dabei wird nur über den Betrag einer Zahl nachgedacht,
nicht einbezogen das -9 als Dreifaches von -3 eigentlich eine kleinere Zahl ergibt 


so richtig definiert wurde das bei uns auch nie, aber -2.5 gerundet auf -2, das wäre mir in der Schule oder im Studium in Erinnerung geblieben


----------



## xehpuk (22. Mrz 2011)

Da kommt es dann darauf an, wie formal korrekt man sich ausdrückt. Wie du bereits angedeutet hast, dass 
	
	
	
	





```
3x >= x
```
 bzw. 
	
	
	
	





```
3x > x
```
 falsch ist, solange man sich nicht auf die natürlichen oder positiv reellen Zahlen (im zweiten Fall ohne 0) beschränkt.

Aber wenn man dann sagt, "auf die nächstgrößere *Ziffer*", dann ist es symmetrisches Runden. [Wobei: Wenn man von 9 auf 10 rundet … ]


----------



## henpara (22. Mrz 2011)

Zum Thema: (nach Wikipedia)


> Mathematische Rundung
> 
> Die Mathematische (auch geodätische oder unverzerrte) Rundung ist wie folgt definiert:[1]
> 
> ...


----------



## SlaterB (22. Mrz 2011)

henpara hat gesagt.:


> Also wenn man von 0.5 zur 0 "hochrundet" zweifel ich jetzt erstmal an der Seriosität der Quelle.


von -0.5


----------



## xehpuk (22. Mrz 2011)

*-*.5, nicht .5. 



> * 2,2500 ≈ 2,2 (nach Regel 3 zur geraden Ziffer hin gerundet)
> * 2,3500 ≈ 2,4 (nach Regel 3 zur geraden Ziffer hin gerundet)


Und wie sieht es dann bei 2,3000 aus? Abgerundet (Regel 1) hieße dann wohl, dass es einfach so bleibt.


----------



## henpara (22. Mrz 2011)

Hatte es schon editiert 

@round():


> public static long round(double a)
> 
> Returns the closest long to the argument. The result is rounded to an integer by adding 1/2, taking the floor of the result, and casting the result to type long. In other words, the result is equal to the value of the expression:
> 
> (long)Math.floor(a + 0.5d)


Also nicht symmetrisch gerundet.

Wobei ich vor allem das hier interessant finde:


> Das kaufmännische Runden erzeugt kleine systematische Fehler, da das Aufrunden um 0,5 vorkommt, das Abrunden um 0,5 jedoch nie; das kann Statistiken geringfügig verzerren.



€:


> Und wie sieht es dann bei 2,3000 aus?


garkein problem, da keine 5 enthalten ist wird natürlich abgerundet auf 2,0. Auf eine Stelle hinterm Komma runden macht ja bei 0 ohnehin keinen Sinn, da nichts zu tun ist außer Abschneiden.


----------



## Shulyn (22. Mrz 2011)

xehpuk hat gesagt.:


> [..]
> Ich sehe zumindest das asymmetrische Runden per Math.round() als Standard in der Mathematik. Interessant finde ich auch die Bemerkung zu ROUND_HALF_UP im JavaDoc:[..]



Sehe ich nicht so. Gehen wir mal von einem solchen fall aus :

-1.5 = (-)*1.5    / Mathematisch sollte das passen.

Jetzt runden wir alle Zahlen mit math.round().

-1 = (-)*2

-1 = -2 

Irgendwie kommt das so garnicht hin. :rtfm:
Wie SlaterB schon gezeigt hat, ist die umsetzung von Math.round() sehr schön, aber erzeugt falsche Ergebnisse beim Runden von Negativen Zahlen (-x.5). (Flasch Mathematisch betrachtet)


```
public static long round(double a) {
        return (a < 0 ? -1 : 1) * (long)Math.floor(Math.abs(a) + 0.5d);
    }
```
So würde es passen.


----------



## xehpuk (22. Mrz 2011)

Ich meinte natürlich auf die erste Nachkommastelle runden, aber da trifft wohl einfach Regel 1 zu, dass abgerundet, also abgeschnitten wird (in dem Fall die drei Nullen) => 2,3.

Wobei das mit der statistischen Verzerrtheit auch etwas hat …



Shulyn hat gesagt.:


> -1.5 = (-)*1.5    / Mathematisch sollte das passen.
> 
> Jetzt runden wir alle Zahlen mit math.round().
> 
> ...


Das sind keine mathematischen Ausdrücke, die du da hast. Was soll "(-)*1.5" sein? Etwa "(-1)*1.5"? Runden ist aber nicht multiplikativ, von daher handelt es sich dort eh nicht um Äquivalenzumformungen.


----------

