Java Math.sqrt, Rundungsfehler?

schlelia

Aktives Mitglied
Hallo,
ich fange gerade erst mit Java an und hab eine Übungsaufgabe bekommen. Es handelt sich um diese Methode:
Java:
public static double computeAverageSpeed(double t, double m) {
        double a = (8 * PhysicsConstants.BOLTZMANN * t) / (Math.PI * m);
        return Math.sqrt(a); // TODO
    }

PhysicsConstants.BOLTZMANN ist einfach 1.380649E-23.

Nun soll es folgenden Test erfüllen:
Java:
@Test(timeout = 666)
    public void pubTest_computeAverageSpeed_hotOxygen() {
        double molarMass_Oxygen = 0.0319988; // kg/mol
        double expected = 451.54529119983204; // m/s
        double actual = Physics.computeAverageSpeed(PhysicsConstants.NORMTEMPERATURE + 35, molarMass_Oxygen);
        double expectedSimple = expected * Math.sqrt(3 * Math.PI / 8);
        assertTrue(Math.abs(expected - actual) < 1E-4 || Math.abs(expectedSimple - actual) < 1E-4);
    }
PhysicsConstants.NORMTEMPERATURE = 273.15
Bei mir funktioniert das noch nicht. Ich verstehe einfach nicht warum, kann mir da jemand helfen?
Danke
 

LimDul

Top Contributor
Ohne es mir im Detail anzusehen - Fließkommazahlen sind inhärent ungenau und bei Berechnungen mit derartig vielen Nachkommastellen kommen schnell Abweichungen rein.
 
M

Mart

Gast
alle zahlen können nur binär gespeichert werden dh mit bits werden die dann eingetragen und nachkommastellen machen da immer probleme zb 2.5 gibts nicht exakt in binär das ist dann 2.49888 irgendwas... soweit ich mich richtig erinnere deswegen sind komma zahlen sehr kritisch zu betrachten es passiert aber ansich kein "Fehler"
 

Robert Zenz

Top Contributor
Hallo,
ich fange gerade erst mit Java an und hab eine Übungsaufgabe bekommen.

Wie bereits gesagt, Gleitkommazahlen haben bei Definition eine Ungenauigkeit. Daher sollten diese nur verwendet werden wenn man mit der Annaeherung an das eigentlich Ergebnis leben kann (zum Beispiel wenn man eine Grafik zeichent).

Wenn mann ein genaues Ergebnis braucht, oder eine groeszere Genauigkeit als float/double bietet, kann man in Java BigDecimal verwenden. Hierbei handelt es sich um eine Klasse welche Zahlen mit arbitraerer Genauigkeit darstellen.

Grob umgestellter Code:

Java:
BigDecimal molarMass_Oxygen = new BigDecimal("0.0319988"); // kg/mol
BigDecimal expected = new BigDecimal("451.54529119983204"); // m/s
BigDecimal actual = Physics.computeAverageSpeed(PhysicsConstants.NORMTEMPERATURE.add(new BigDecimal("35)), molarMass_Oxygen);
BigDecimal expectedSimple = expected.multiply(new BigDecimal("3").multiply(BigDecimal.PI).divide(new BigDecimal("8")).sqrt();

Hinweis noch, es gibt einen Unterschied bei den Kosntruktoren von BigDecimal:

Java:
BigDecimal ungenau = new BigDecimal(1.234567); // Nimmt den ungenauen float-Wert.
BigDecimal genau = new BigDecimal("1.234567"); // Nimmt den exakten Wert wie im String.
 
Zuletzt bearbeitet:

httpdigest

Top Contributor
expected = 451.54529119983204
expectedSimple = 490.1081088031151
actual = 5.818699625926643E-10

Also eine Abweichung von ca 12 Grössenordnungen!
Das hat garantiert rein gar nichts mit Fließkommaungenauigkeit zu tun.
Meine Vermutung: Deine Rechnung ist einfach komplett falsch oder expected ist nicht das, was rauskommen soll.

EDIT: Und Fehler misst man auch eher nicht absolut, sondern relativ. Und das aus eben dem genannten Grund der Fließkommaungenauigkeit. Also Fehler ist nicht einfach der absolute Abstand von actual und expected, sondern der relative, z.B.: abs((actual - expected) / expected) und darauf kann man dann eine gewünschte Abweichung (von z.B. 0,5% oder so) definieren.
 
Zuletzt bearbeitet:

schlelia

Aktives Mitglied
expected = 451.54529119983204
expectedSimple = 490.1081088031151
actual = 5.818699625926643E-10

Also eine Abweichung von ca 12 Grössenordnungen!
Das hat garantiert rein gar nichts mit Fließkommaungenauigkeit zu tun.
Meine Vermutung: Deine Rechnung ist einfach komplett falsch oder expected ist nicht das, was rauskommen soll.

EDIT: Und Fehler misst man auch eher nicht absolut, sondern relativ. Und das aus eben dem genannten Grund der Fließkommaungenauigkeit. Also Fehler ist nicht einfach der absolute Abstand von actual und expected, sondern der relative, z.B.: abs((actual - expected) / expected) und darauf kann man dann eine gewünschte Abweichung (von z.B. 0,5% oder so) definieren.
Aber ich hab genau die Formel angewendet, die gegeben war. https://de.wikipedia.org/wiki/Maxwell-Boltzmann-Verteilung#Mittlere_Geschwindigkeit . Ich habe das schon tausend mal überprüft
 

mihe7

Top Contributor
Ich verstehe nicht wie da was komplett anderes bei mir rauskommt. Dann kann ja nur irgendwo eine Einheit nicht passen
Es liegt daran, was ich oben geschrieben habe. Du bekommst die molare Masse M. Wenn ich das in die Formel für die molare Masse einsetze, erhalte ich als Ergebnis: Math.sqrt(8*1.380649E-23*6.02214076E23*308.15/(Math.PI*0.0319988)) und damit 451.5453660559818
 

schlelia

Aktives Mitglied
Es liegt daran, was ich oben geschrieben habe. Du bekommst die molare Masse M. Wenn ich das in die Formel für die molare Masse einsetze, erhalte ich als Ergebnis: Math.sqrt(8*1.380649E-23*6.02214076E23*308.15/(Math.PI*0.0319988)) und damit 451.5453660559818
Und woher kommen die 6.02214076E23 genau? Sry dass ich das nicht so verstehe
 

mihe7

Top Contributor
Das ist die Avogadro-Konstante zwecks Umrechnung in Teilchenmasse: M = NA * m <=> m = M/NA, also 1/m = NA/M.

Wenn du in der Formel v=sqrt(8kBT/(πm)) den Term unter der Wurzel betrachtest:

gif.latex
 

Neue Themen


Oben