Problem mit Nachkommastellen, die es nicht geben sollte

  • VB.NET

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von VaporiZed.

    Problem mit Nachkommastellen, die es nicht geben sollte

    Guten Morgen allerseits,

    ich habe ein Problem mit Zahlen, die ich einer Access Tabelle entnehme. Diese Zahlen lasse ich in mehreren Labeln in meinem VB.NET Programm anzeigen.
    Nun verhält es sich so, dass manche Zahlen plötzlich verändert dargestellt werden. Die Zahlen habe ich aus einer Excel Tabelle in Access importiert.
    Drei Nachkommastellen sind vorhanden und die Einstellungen in Access für die Spalte sind wie folgt: (Feldgröße: Double / Nachkommastellen: 3)

    Sowohl in Access als auch in Excel wird z.B. 1,447 angezeigt. In meinem Programm im Label steht dann jedoch 1,446999. Wo wird nun 0,000001 davon abgezogen???
    Oder passen der Datentyp "Double" und das Label nicht zusammen?
    Ich wäre für Hilfe sehr dankbar. :)
    Nur zur Info. Wenn du in Access double mit 3 Nachkommastellen angibst, dann wird die Zahl trotzdem komplett gespeichert und nur die Ansicht ist auf 3 Stellen beschränkt.
    Ist eine reine Formatierungseinstellung für Access.
    Selbiges gilt im Zweifel für Excel (je nachdem wie man es dort macht).

    LG
    Das ist meine Signatur und sie wird wunderbar sein!

    Narretei schrieb:

    Das liegt an den Quantisierungsstufen (siehe de.wikipedia.org/wiki/Quantisierungskennlinie) der Double-Zahlen. Das ist kein Fehler. Runde einfach in der Darstellung deine Zahlen auf die gewünschte Anzahl Nachkommastellen. Das funktioniert mit Math.Round().


    Danke für den Tipp :) Leider habe ich noch nicht raus wie ich den Math.Round Befehl korrekt einsetzen kann, da die Daten ja direkt in das Label geladen werden, da ich die Access Datenbank als Datenquelle verknüpft habe. Den Inhalt des verknüpften Labels manuell zu ändern funktioniert so leider bei mir nicht :/


    Kann ich das Format in der Access Datenbank anpassen, damit das nicht mehr passiert?


    Mono schrieb:

    Nur zur Info. Wenn du in Access double mit 3 Nachkommastellen angibst, dann wird die Zahl trotzdem komplett gespeichert und nur die Ansicht ist auf 3 Stellen beschränkt.
    Ist eine reine Formatierungseinstellung für Access.
    Selbiges gilt im Zweifel für Excel (je nachdem wie man es dort macht).

    LG


    Vielen Dank, das erklärt einiges :)
    @FloMZ

    Narretei schrieb:

    Math.Round()
    ist zur Darstellung suboptimal.
    Formatiere die darzustellende Zahl mit String.Format().
    Beispiel:

    VB.NET-Quellcode

    1. MessageBox.Show(String.Format("{0:0.0}", Math.PI))
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:


    ist zur Darstellung suboptimal.
    Formatiere die darzustellende Zahl mit String.Format().

    ich würde hier nicht unerwähnt lassen, dass aus 1,49 dann 1,4 wird. war unsinn

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Narretei“ ()

    Narretei schrieb:

    dass aus 1,49 dann 1,4 wird.
    Bei mir nicht:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:


    Formatiere die darzustellende Zahl mit String.Format().


    Kann ich diese Formatierung in den Label Eigenschaften vornehmen? Mir ist unklar, wie ich es anwenden soll, da die Labels ja automatisch erzeugt wurden, als ich eine Access Tabelle als Datenquelle eingefügt habe. Deshalb finden sich die einzelnen Labels (noch) nicht im Quellcode wieder.
    @FloMZ Dann mach Dir eine eigene Label-Klasse, die von Label erbt.
    Gib ihr eine Property mit der Format-Information und eine Property .Value, in der Du den Label.Text mit Deinem formatierten Wert ausgibst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich verfolge zur Zeit folgenden Ansatz: Ich möchte die alten Label ausblenden und neue mit den gerundeten Werten anzeigen lassen.
    Leider funktioniert keine der bislang genannten Methoden, um die unerwünschten Nachkommastellen zu beseitigen.

    Ich rufe mir zunächst den Wert des automatisch erzeugten Labels in eine Zwischenvariable x:

    VB.NET-Quellcode

    1. ​Dim x As Double = Label1.Text


    Dann habe ich folgende Formatierungsversuche bisland unternommen (immer nur einer auf einmal versteht sich):

    VB.NET-Quellcode

    1. ​Label2.Text = String.Format("{0:0.00}", x)
    2. x.ToString("0.00")
    3. Math.Round(x)
    4. Math.Round(x, decimals:=3)


    Dann lasse ich mir in dem neuen Label2 den (eigentlich) gerundete Wert von x ausgeben:

    VB.NET-Quellcode

    1. ​Label2.Text=x


    Egal mit welcher Methode, es wird beharrlich statt 2,54 zum Beispiel 2,53999 angezeigt, und ich verstehe einfach nicht warum. Kann mir bitte jemand helfen vom Schlauch runter zu kommen? :P
    x ist eine Variable mit dem genauen Wert. Deine Rundungsversuche im 2. Codeblock sind nett. Haben aber keine Auswirkungen auf x selbst. Du würdest nur was sehen, wenn Du die Rundungen an das Label weiterreichst. Du reichst aber nur x weiter. Also den genauen, ungerundeten Wert.
    btw: Dass da der Compiler nicht meckert, weist darauf hin, dass Du Option Strict Off hast.
    Also probier z.B.:

    VB.NET-Quellcode

    1. Label2.Text = x.ToString("0.00")

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    *unnötiges Zitat entfernt*


    Vielen Dank für die Antwort. Es funktioniert teilweise. Ich bin nun auf eine seltsame Eigenart gestoßen. Diese Rundung geschieht immer, wenn ein neuer Index in einer ComboBox gewählt wurde. Nun ist es so, wenn ich das erste Mal Eintrag X in der ComboBox auswähle, so wird der Wert weiterhin in beiden Labels falsch angezeigt (2,53999 statt 2,54). Wenn ich dann einen anderen anwähle, und dann wieder X, funktioniert es und der Wert wird korrekt gerundet ausgegeben. Wie kommt es dazu? Warum erst beim zweiten Mal?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    1. Was denn für ne ComboBox?
    2. Wann wird denn der Rundungs- und Zuweisungscode ausgeführt? Im ComboBox-SelectedIndexChanged-EventHandler? Und wie sieht der momentan aus?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed: Die Combobox wurde via DataGridView erstellt. Die Label werden automatisch, entsprechend der Auswahl in der Combobox "befüllt". Die Datenquelle ist eine Accesstabelle.

    Der Code sieht wie folgt aus:

    VB.NET-Quellcode

    1. Private Sub MaterialnummerComboBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles MaterialnummerComboBox.SelectedIndexChanged
    2. 'ProzessHHLabel1.Visible = True
    3. Dim x As Double = ProzessHHLabel1.Text
    4. Label12.Text = x.ToString("0.000")
    5. End Sub
    Hi,

    stell doch wie schon einmal vorgeschlagen auf

    Option Strict ON

    Schon sowas hier geht normal nicht:

    VB.NET-Quellcode

    1. Dim x As Double = ProzessHHLabel1.Text


    Da du nicht mit Option Strict ON programmierst werden immer wieder wirre und unerklärliche Fehler auftreten.

    Dann frage ich mich gerade was die Combobox mit dem Label zu tun haben.
    Setz doch mal einen Debug-Haltepunkt an die von dir gepostete Stelle und schau mal, ob das Programm beim ersten Mal überhaupt dahin kommt.
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Das mit Strict ON habe ich nun gemacht und alle Fehler ausgebessert. Leider keine Besserung mit:

    VB.NET-Quellcode

    1. Dim x As Double = CDbl(ProzessHHLabel1.Text)
    2. Label12.Text = x.ToString("0.000")


    Das mit dem Haltepunkt habe ich schon probiert. Es wird der korrekte Wert angezeigt im Quelltext. Auf dem Label steht dann aber leider der falsche. Auf dem Label wird auch nicht die Anzahl der Nachkommastellen (3) berücksichtigt. Beispiel: Während der Debug Haltepunkt 2,100 anzeigt, steht auf dem Label 2,10.

    Was mich nun vollends verwirrt hat, ist dass auch der Wert, der direkt aus der Accessdatei gezogen wird, sich genau so verhält. Es gibt also eine Art Rückkopplung, obwohl das nirgends absichtlich von mir umgesetzt wurde. Also beim ersten Mal wählen in der ComboBox der falsche Wert, beim zweiten Mal zeigen dann beide den korrekten Wert an...
    So,

    ich hab mir jetzt nen Label gebaut, indem ich manuell den Wert "2,10" als Text gesetzt habe.
    Daneben nen Button mit:

    VB.NET-Quellcode

    1. Label1.Text = Convert.ToDouble(Label1.Text).ToString("N3")

    Sobald ich den Button betätige steht da statt "2,10" ein "2,100"
    Vielleicht ist mir auch zu unverständlich was hier getrieben wird, aber ich verstehe nur, in nem Label steht nen Text von 2,10 und du willst 2,100 da stehen haben. (Warum auch immer man da den Wert des Label.Text formatiert und nicht direkt die korrekte Formatierung ans Label übergibt verstehe ich nicht)
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Leider hast du recht, ich finde dieses Problem sehr nervig. Der eigentlich schöne Automatismus, der mir die Daten aus meiner Access Tabelle ausgibt, funktioniert leider nicht korrekt. In der Access Tabelle stehen Dezimalzahlen mit drei Nachkommastellen. Genau so würde ich sie auch automatisch in den Labels ausgeben lassen. Leider wird aus einer 2,100 eine 2,10 (was noch verkraftbar ist). Jedoch verändert sich manchmal auch der Wert der Zahl, was nicht akzeptabel ist. Wie ich aus dem zweiten Beitrag hier im Thread entnommen habe liegt es an "Das liegt an den Quantisierungsstufen"... Deshalb wird wohl aus den 2,540 in meiner Access Tabelle eine 2,539999. Und so ist es leider mit gut 20-30% der Zahlen die übergeben werden.

    Eigentlich übergebe ich die richtigen Zahlen. Der Umweg über ein Label welches das eigentliche Label ersetzen soll gehe ich nur, da ich ich nicht weis wie ich in den Automatismus eingreifen könnte.
    Die Frage die ich mir stelle ist... Wie holst du denn die Daten aus Access. Automatismus sagt ja nix aus.
    Es gibt ja gefühlt 100 Wege Daten aus ner Datenbank zur Anzeige in ner Form zu bringen.

    Machst alles manuell?
    Nutzt du nen Dataset wie der EDR das immer gerne vorschlägt? Es wäre doch der Sinnvolle weg, während des Füllens direkt die Daten so aufzubereiten dass es passt und nicht danach.
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D