none
Werte werden "ungenau" aus Textdatei eingelesen RRS feed

  • Frage

  • Hi,

    ich möchte Werte aus einer Textdatei einlesen, die ich dann in ein Array mit doppelter Genauigkeit schreibe. Das Problem ist nun, dass die Werte nicht exakt übernommen werden. Die Erste Zahl in der Textdatei lautet z.B. -3,81. In das Array wird aber -3.809999942779541 geschrieben. Die Abweichung ist zwar gering, aber ich brauche die hohe Genauigkeit. Ich vergleiche zwei Temperaturfelder auf Unterschiede, und wenn schon die Ausgangswerte nicht exakt eingelesen werden, klappt das natürlich nicht.

    Hier der Programmcode für das Einlesen. Hat jemand eine Idee, wie die ungenauigkeiten entstehen?

            REM ProgressivBar1 auf Schichttemperaturen lesen vorbereiten
            ProgressBar1.Value = 0
            ProgressBar1.Maximum = YMAX
    
            REM Schichttemperaturen lesen
            LabelProgressivBar.Text = "Schichttemperaturen einlesen"
            Refresh()
            Dim sr As New StreamReader("C:\FEM-DA\10mm-DA.txt")
    
            For y As Integer = 0 To YMAX
                Temp2D(y) = Convert.ToSingle(sr.ReadLine())
                ProgressBar1.PerformStep()
            Next
    
    Gruß, Thomas

    Donnerstag, 19. April 2012 08:17

Antworten

  • Temp2D(y) = Convert.ToDouble(sr.ReadLine())

    ... konvertiere den string in eine Zahl vom Typ double.

    (Eventuell auch interressant double.Parse und double.TryParse faalls Du nicht vorher genau weißt, dass der Text in einen Double gewandelt werden kann http://msdn.microsoft.com/de-de/library/system.double.tryparse(v=vs.100).aspx )

     Du wolltest doch doppelte Genauigkeit? (Die Abweichung kommt, davon, dass ein Single die Zahl eventuell nicht exact abbilden kann. http://de.wikipedia.org/wiki/Gleitkommazahl )

    Viele Grüße,

      Thorsten


    Donnerstag, 19. April 2012 12:27
  • Wichtig ist zu verstehen, dass die interne binäre Darstellung gebrochener Zahlen und die Umwandlung dieser binären Darstellung in eine dezimale Darstellung mit Rundungsdifferenzen behaftet sein kann. Die dezimale Darstellung der Zahl 3,81 lässt sich nicht genau in eine kurze binäre Mantisse (Single) umwandeln. Da werden einige benötigte Bits abgeschnitten. Wenn solch eine Gleitkommazahl dann zurück in eine dezimale Darstellung umgewandelt wird und die maximal mögliche Zahl dezimaler Nachkommastellen genutzt wird, kann es zu dem beobachteten Ergebnis kommen.
     
    Es gibt 3 Lösungswege:
    - Rundung der Darstellung
    - Nutzung einer langen Gleitkommadarstellung (Double)
    - Nutzung des Typs Decimal
    --
    Viele Gruesse
    Peter
    • Als Antwort markiert ThomasPeterSN Freitag, 20. April 2012 06:21
    Freitag, 20. April 2012 06:00

Alle Antworten

  • Temp2D(y) = Convert.ToDouble(sr.ReadLine())

    ... konvertiere den string in eine Zahl vom Typ double.

    (Eventuell auch interressant double.Parse und double.TryParse faalls Du nicht vorher genau weißt, dass der Text in einen Double gewandelt werden kann http://msdn.microsoft.com/de-de/library/system.double.tryparse(v=vs.100).aspx )

     Du wolltest doch doppelte Genauigkeit? (Die Abweichung kommt, davon, dass ein Single die Zahl eventuell nicht exact abbilden kann. http://de.wikipedia.org/wiki/Gleitkommazahl )

    Viele Grüße,

      Thorsten


    Donnerstag, 19. April 2012 12:27
  • Richtig, ich wollte ein Array mit doppelter Genauigkeit, das war mein Fehler im Programmcode. Die Zahl, die ich einlesen wollte, hat aber doch nur zwei Kommastellen, da dachte ich, dass auch ein Array mit einfacher Genauigkeit die exakt abbilden kann. Bei einer Zahl wie z.B. -3,81 in der Textdatei hätte ich  -3.810000000000000 im Array erwartet.

    Wie auch immer, ich habe den Programmcode geändert und es funktioniert. Ich werde mal den Wikipedia-Artikel studieren, vielleicht weiß ich hinterher auch, warum. ;-)

    Vielen Dank für die Hilfe.

    Gruß, Thomas

    Donnerstag, 19. April 2012 15:40
  • Ich kann zwar nur raten, aber ein Single ist 32Bit und ein Double 64Bit groß, ich würde sagen da werden einfach 4 Bytes zuviel mitausgelsen die dann dieses verhalten erklären.

    Koopakiller - http://koopakiller.ko.ohost.de/

    Donnerstag, 19. April 2012 15:43
  • Richtig, ich wollte ein Array mit doppelter Genauigkeit, das war mein Fehler im Programmcode. Die Zahl, die ich einlesen wollte, hat aber doch nur zwei Kommastellen, da dachte ich, dass auch ein Array mit einfacher Genauigkeit die exakt abbilden kann. Bei einer Zahl wie z.B. -3,81 in der Textdatei hätte ich  -3.810000000000000 im Array erwartet.

    Wie auch immer, ich habe den Programmcode geändert und es funktioniert. Ich werde mal den Wikipedia-Artikel studieren, vielleicht weiß ich hinterher auch, warum. ;-)

    Vielen Dank für die Hilfe.

    Gruß, Thomas

    Hallo Thomas,

    bitte lese: Standard numeric format strings Die Ausgabe Formatierung einer Zahl Kannst Du damit steuern.

    3.81000000000  muss nicht sein.

    Gruss Ellen


    Ich benutze/ I'm using VB2008 & VB2010

    Donnerstag, 19. April 2012 18:49
  • Hallo Ellen,

    das Formatieren der Zahl ist nicht mein Problem. Ich hätte nichts dagegen, wenn nach dem Einlesen der -3,81 aus der Textdatei im Array -3.810000000000000 stehen würde. Dort stand aber -3.809999942779541, zumindest solange ich den Wert aus der Textdatei mit ConvertToSingle() eingelesen habe. Mit ConvertToDouble() klappte es dann.

    Hallo Koopakiller,

    ich weiß nicht, ob ich Deine Vermutung richtig verstehe. In der Textdatei, aus der ich einlese sind 2000 Zeilen enthalten. In jeder Zeile steht eine Zahl mit max. zwei Kommastellen. Alle 2000 Zahlen werden korrekt in das Array eingelesen, allerdings jede Zahl mit einer (geringen) Ungenauigkeit. Ich weiß nicht, ob das so passieren würde, wenn jeweils vier Byte zuviel ausgelesen werden würden.

    Gruß, Thomas



    Donnerstag, 19. April 2012 20:07
  • Wichtig ist zu verstehen, dass die interne binäre Darstellung gebrochener Zahlen und die Umwandlung dieser binären Darstellung in eine dezimale Darstellung mit Rundungsdifferenzen behaftet sein kann. Die dezimale Darstellung der Zahl 3,81 lässt sich nicht genau in eine kurze binäre Mantisse (Single) umwandeln. Da werden einige benötigte Bits abgeschnitten. Wenn solch eine Gleitkommazahl dann zurück in eine dezimale Darstellung umgewandelt wird und die maximal mögliche Zahl dezimaler Nachkommastellen genutzt wird, kann es zu dem beobachteten Ergebnis kommen.
     
    Es gibt 3 Lösungswege:
    - Rundung der Darstellung
    - Nutzung einer langen Gleitkommadarstellung (Double)
    - Nutzung des Typs Decimal
    --
    Viele Gruesse
    Peter
    • Als Antwort markiert ThomasPeterSN Freitag, 20. April 2012 06:21
    Freitag, 20. April 2012 06:00
  • Ich glaube, jetzt habe ich es begriffen. Mit der doppelten Genauigkeit klappt das Einlesen jetzt auch so, wie es soll. Mit dem Typ Decimal werde ich mich auch mal beschäftigen, den habe ich bisher nie benutzt.

    Danke an alle für die Hilfe.

    Gruß, Thomas

    Freitag, 20. April 2012 06:29