Convert.ToDouble Präzision



  • Hey

    ich möchte einen String in einen Double konvertieren:

    string x = -64.00623665093068;
    string y = -64.006236650930688;
    
    double dvalx = Convert.ToDouble(x, CultureInfo.InvariantCulture.NumberFormat)
    double dvaly = Convert.ToDouble(y, CultureInfo.InvariantCulture.NumberFormat)
    

    Im Debugger siehts dann so aus:

    dvalx <=> -64.006236650930674
    dvaly <=> -64.006236650930688
    

    Ich weiß, dass es zu Ungenauigkeiten etc kommen kann, auch hängt das von der Implementierung von ToDouble ab, aber vielleicht mache ich ja doch etwas verkehrt... wenn ja, bitte Bescheid sagen 🙂

    Ps.: Ich muss Double benutzen, kein Dezimal vorschlagen bitte 🙂

    Danke euch!

    EDIT:
    Vielleicht noch eine andere Frage dazu: Kann man eventuell die Anzahl der Nachkommastellen irgenwie einstellen? Oder generell die Genauigkeit?
    Danke!



  • Wenn du mal double xd = -64.00623665093068; gemacht hättest, hättest du gesehen das dort auch -64.006236650930674 bei raus kommt, genau wie beim double.Parse.

    Warum das so ist weiß ich auch nicht, vor allem wo die längere Zahl korrekt ist.
    Die double Präzision ist lauf MSDN bei 14-15.

    PS. In der Consolenausgabe ist der Wert anders als in Visual Studio im Watch.

    static void Main(string[] args)
    {
    	string x = "-64.00623665093068";
    	double xd = -64.00623665093068;
    	string y = "-64.006236650930688";
    	double yd = -64.006236650930688;
    
    	double dvalx = Convert.ToDouble(x, CultureInfo.InvariantCulture.NumberFormat);
    	double dvaly = Convert.ToDouble(y, CultureInfo.InvariantCulture.NumberFormat);
    
    	double dvalx2 = double.Parse(x, CultureInfo.InvariantCulture.NumberFormat);
    	double dvaly2 = double.Parse(y, CultureInfo.InvariantCulture.NumberFormat);
    
    	Console.WriteLine(x);
    	Console.WriteLine(xd);
    	Console.WriteLine(dvalx);
    	Console.WriteLine(dvalx2);
    
    	Console.WriteLine(y);
    	Console.WriteLine(yd);
    	Console.WriteLine(dvaly);
    	Console.WriteLine(dvaly2);
    }
    


  • Darf man denn fragen, warum es double sein muss? Aufgabe vom Prof?



  • David W schrieb:

    Wenn du mal double xd = -64.00623665093068; gemacht hättest, hättest du gesehen das dort auch -64.006236650930674 bei raus kommt, genau wie beim double.Parse.

    und bei quasi sämtlichen Online Convertern 😉



  • Wenn du mal double xd = -64.00623665093068; gemacht hättest, hättest du gesehen das dort auch -64.006236650930674 bei raus kommt, genau wie beim double.Parse.

    Ok, aber ich verstehe nicht ganz, warum ich double in double parsen sollte?!

    und bei quasi sämtlichen Online Convertern 😉

    und nu? 🙂

    Die double Präzision ist lauf MSDN bei 14-15.

    Bei anderen Zahlen ist mir aufgefallen, dass die Vorkommastellen scheinbar auch zählen. Nur bei manchen langen Zahlen (wie bei der längeren hier) gehts (meine ich, sizte erst morgen wieder am rechner).

    naja, also bei double nur 15 Stellen Genauigkeit. bleibt dann die frage, wieso die kleinere zahl scheinbar falsch konvertiert wird.. wobei mir das grad nicht soo wichtig ist, ich brauche nur das Ergebnis 🙂

    Danke euch fürs mitspekulieren 🙂



  • iop schrieb:

    bleibt dann die frage, wieso die kleinere zahl scheinbar falsch konvertiert wird..

    Weil double (und float) nur bestimmte Zahlen darstellen können.



  • iop schrieb:

    Wenn du mal double xd = -64.00623665093068; gemacht hättest, hättest du gesehen das dort auch -64.006236650930674 bei raus kommt, genau wie beim double.Parse.

    Ok, aber ich verstehe nicht ganz, warum ich double in double parsen sollte?!

    Sagt doch keiner das du Convertieren sollst.
    Mach einfach mal

    double xd = -64.00623665093068;
    

    Und schau was Visual Studio dir da danach als Wert bei xd anzeigt. Du wirst merken das es auch verändert wird. Dadurch ist es direkt ein Indikator für den Gültigkeitsbereich.

    Ich vermute das es bis Stelle 15 gültig ist, alles darüber ist dann nur noch reine Glückssache.



  • @David
    Ja, jetzt verstehe ich auch was Du meinst. Ich sollte nicht so spät noch im Forum posten 🙂
    Wäre ich jetzt aber gar nicht drauf gekommen, die Zahl einfach so mal zu untersuchen, Du bist gut 😉

    Ok, Danke euch allen für die Hilfe!



  • David W schrieb:

    Warum das so ist weiß ich auch nicht, vor allem wo die längere Zahl korrekt ist.

    Ich tippe mal darauf, dass die beiden nächstliegenden darstellbaren double-Zahlen ca. -64.006236650930674 und -64.006236650930688 sind. Die längere entspricht also zufällig genau der einen darstellbaren Zahl, die kürzere liegt irgendwo dazwischen. Die darstellbare Zahl mit ...74 ist näher dran und wird genommen.

    Die double Präzision ist lauf MSDN bei 14-15.

    Das ist ganz nett zu wissen, aber für ernsthafte Überlegungen nicht zu gebrauchen. Computer rechnen binär, deshalb musst du dir die Präzision in Binärstellen angucken. Das sind bei double 52 Bits (dazu kommen 11 Bits für den Exponent und 1 fürs Vorzeichen, macht 64 insgesamt).

    Um sich da über die Größenordnungen klar zu werden: -64,xxx sind -1,yyy*26. Die 1 vor dem Komma ist bei normalisierten Zahlen implizit, die 52 Bits entfallen also auf yyy. Zwei beieinanderliegende Zahlen unterscheiden sich in dem Bereich also um 2-5226 = 2-46 ≈ 1.421085471520210-14. Das ist genau der Unterschied der beiden darstellbaren Zahlen oben. Man nennt das auch Maschinen-Epsilon (wobei sich der Begriff ohne weitere Zusätze immer auf Zahlen in der Größenordnung 1 bezieht, genauer: ε ist die kleinste positive Zahl, so dass 1+ε ≠ 1)

    edit: bisschen aufgehübscht :xmas2:



  • @Bashar: Gefällt Mir!



  • Jo, gute Erklärung 👍
    Erinnert mich daran, dass ich auch mal wieder den elendig langen Text zu Fließkommazahlen etwas auffrischen sollte 🙂


Anmelden zum Antworten