rechnet sun-jdk falsch?

  • ich habe ein package 'calculator' mit einer klasse 'CalculatorFunctions' und einigen methoden, die sehr einfach gestrickt sind. in folgender art und weise:

    Code
    public double subtract(double number1, double number2) {
            return number1 - number2;
        }


    diese werden in einer testbench aufgerufen:

    Code
    public void testSubtract1() {                
                double myvalue=cf.subtract(3.2, 2.5);
                System.out.println("Subtract1: " + myvalue);
                assertTrue(myvalue == 0.7);
            }


    das objekt 'cf' wurde zuvor angelegt:

    Code
    calculator.CalculatorFunctions cf = new calculator.CalculatorFunctions();


    beim 'println' kommt nun folgendes raus:

    Code
    Subtract1: 0.7000000000000002


    eine ebenso einfach gestrickte methode 'multiply' liefert zb bei 'multiply(3.4,8.2)' den wert 'Multiply1: 27.879999999999995'

    das ganze passiert mit sun-jdk 1.5.0_06 unter x86/win2k

    was mache ich falsch?

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

  • Zitat von Kampi

    was mache ich falsch?


    Du rufst dir nicht das minimale Grundwissen in Erinnerung, das du in Grundzüge der Informatik über Numerik erworben hast.
    Die Kurzfassung: Computer können nicht rechnen, und wenn es um Subtraktion geht, sind die Ergebnisse ganz besonders phantasievoll frei erfunden.

    *plantsch*

  • okay, alles klar. hab zwar an die interne darstellung gedacht dies aber anscheinend verworfen, weil ich mich zu stark an den ppc/blackdown bug den ich vor kurzem hatte erinnert fuehlte. what ever.

    was ist aber nun eurer meinung nach die sinnvollste moeglichkeit einen vergleich durchzufuehren? wenn ich auf 'float' caste, dann funktionierts. in dem fall werd ich auch keine probleme durch den cast bekommen, aber wie macht mans wenn man von java ahnung hat?

    Willfähriges Mitglied des Fefe-Zeitbinder-Botnets und der Open Source Tea Party.

  • Ich weiß nicht wie oft ich schon float/real/double Werte miteinander verglichen habe. Allerhöchstens mit Toleranz. Vielleicht ist das für dich auch akzeptabel?

    640K ought to be enough for anybody. :eek2:

  • Zitat von Kampi

    wenn ich auf 'float' caste, dann funktionierts.

    das stimmt vielleicht in diesem fall, aber dafür stimmen dann andere rechnungen wieder nicht. ein cast auf float bringt rein gar nichts. am ehesten funktionierts noch wenn du eine kleine toleranz akzeptierst.

  • Kurz gesagt: Nur Halbe, Viertel, Achtel, Sechzehntel (...) und diverse Zusammensetzungen sind genau darstellbar. 0.7 kriegst du nicht genau hin.

    Am einfachsten mit Toleranz vergleichen, statt if (x=0.7) schreibst halt if (abs(x-0.7) < 0.0000001) oder so.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • jup, gleitkommazahln sollt man nie exakt vergleichn sondern immer mit einem kleinen delta.

    I came here to chew gum and kick ass, and I'm all out of gum...

  • sinnvoll ist es fl oder double zu runden und dann erst zu vergleichen und die abweichung einbeziehen beim vergleichen

    "Am Anfang war ich, und dann kamst du,
    und nun wird mir schlecht :-)):devil:
    "

  • nein, du rundest natürlich nicht auf 0 Kommastellen sondern z.B. auf 5 Kommastellen genau! damit bleibt 3.48 auch 3.48, aber 1.234567 ist dann halt1.23457

  • Das funktioniert eben nicht. Das Rundungsergebnis wird in genausoeinem Float-Register gespeichert, wie die Zahl vorher, da gibts auch dieselben Probleme.
    Mit Toleranz vergleichen, oder nen Integer zu einer Fixkommazahl umbauen, das kann funktionieren.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • Zitat von Wolfibolfi

    Das funktioniert eben nicht. Das Rundungsergebnis wird in genausoeinem Float-Register gespeichert, wie die Zahl vorher, da gibts auch dieselben Probleme.
    Mit Toleranz vergleichen, oder nen Integer zu einer Fixkommazahl umbauen, das kann funktionieren.



    warum nicht ich meine eine zwangs casten oder halt eine abrundung machen bspw nach 3 stellen nach den kommer mit round() .

    "Am Anfang war ich, und dann kamst du,
    und nun wird mir schlecht :-)):devil:
    "

  • Zitat von thanatos5

    warum nicht ich meine eine zwangs casten oder halt eine abrundung machen bspw nach 3 stellen nach den kommer mit round() .

    ja, und das wird dann wieder ungenau gespeichert, sodass die achte stelle nach dem komma nicht passt. vielleicht solltest du dich mal damit befassen, wie ein computer gleitkommazahlen speichert.

  • Tja, wenn du binär rundest, dann funktionierts. Da müsstest du aber 0,8(10) auf 0,75(10) runden, weil da 0,11001...(2) auf 0,11(2) gerundet wird.

    Und gefühlsmäßig ist 0,8 zwar ein gerundetes 0.75, im Binärsystem ists aber umgekehrt. Denk nicht im Dezimalsystem, das bringt dir nix.

    In einen FBO rendern ist wie eine Schachtel Pralinen - man weiß nie, was man kriegt.

  • Zitat von Spockman

    Verwend java.math.BigDecimal zum exakten Rechnen mit arbitrary-precision Dezimalzahlen in Java.


    ist es das was du gemeint hast?

    PHP
    Trux@NOTEBOOK~
    $ java Test
    0.7000000000000002
    0.70000000000000017763568394002504646778106689453125
    0.7000000000000002
  • Zitat von Trux

    ist es das was du gemeint hast?

    Nein.

    Java
    import java.math.BigDecimal;
    
    
    public class Test{
        public static void main(String[]){
            BigDecimal b1 = new BigDecimal("3.2");
            BigDecimal b2 = new BigDecimal("2.5");
            System.out.println(b1.subtract(b2));
        }
    }


    $ java Test
    0.7

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!