Decimal 0.00000000000000 warum nicht 0? Eigene Klasse Property Decimal, aus SQL Datenbank, XML serialisieren

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    Decimal 0.00000000000000 warum nicht 0? Eigene Klasse Property Decimal, aus SQL Datenbank, XML serialisieren

    Hallo,

    ich habe in einer eignen Klasse

    VB.NET-Quellcode

    1. Public Propterty dBestand as Decimal


    in einer externen Datenbank gibt es in einer Tabelle mit einer Spalte fBestand vom Typ Decimal (25,13)
    In meinem Code rufe ich diese Spalte ab und speichere den Wert in einer Instanz meiner Klasse

    VB.NET-Quellcode

    1. MeinObjekt.dBestand = drow("fBestand ")


    Das ganze wird irgendwo anders in ein XML serialisiert und dort habe ich stehen

    XML-Quellcode

    1. <fBestand >0.00000000000000</fBestand >


    Technisch funktioniert das alles. Aber wieso wird nicht einfach eine 0 serialisiert?

    Auch wenn ich mit dem Debugger durchgehe, wird bereits hier eine 0.000000000 zugewiesen und eben keine 0

    VB.NET-Quellcode

    1. MeinObjekt.dBestand = drow("fBestand ")
    @John422 Wo ist das Problem?
    Und:
    Seit wann arbeitet VB6 mit einem Framework?
    Passe Deinen Thread-Header an.
    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!
    OK, verklickt.

    Ich möchte einfach nur aus Interesse wissen, wieso

    MeinObjekt.dBestand = drow("fBestand")
    zu
    <fBestand >0.00000000000000</fBestand >
    serialisiert, wenn in der Datenbank der Wert 0 steht

    aber

    MeinObjekt.dBestand = 0
    zu
    <fBestand >0</fBestand >
    wird, was imho sinn macht.

    Wieso wird in einer Variablen vom typ Decimal nicht automatisch aus 0.00000000000000 > 0?
    @John422 Komisch.
    Ich hab mal fix ne XML-Serialisierung gebaut, da steht <0> drin.
    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!
    Was für ein Booleanwert kommt für Foo raus, wenn Du schreibst Dim Foo = LA.fReserviert = 0?
    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.
    Du hast es doch selbst geschrieben.

    John422 schrieb:

    in einer externen Datenbank gibt es in einer Tabelle mit einer Spalte fBestand vom Typ Decimal (25,13)
    Da sollten also 13 Nachkommastellen stehen.

    Wenn du eintippst

    VB.NET-Quellcode

    1. Dim d1 as Decimal
    2. d1 = 0
    3. Dim d2 = 0.0000D
    4. Dim d3 = 0.00000000000D
    Dann macht er das auch so und die Datenbank macht da nix anderes.

    Der Decimal Datentyp ist kein Gleitkommawert, oder? Das wird der Hauptgrund sein.
    Ein Vergleich sollte nicht scheitern, denn die Differenz ist ja 0 egal wie viele Stellen.

    Mich würde interessieren, was er abgreift wenn die Spalte decimal(25,0) wäre und du in der DB 0.000000000001 einträgst. Kannst ja mal ausprobieren.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Das sind ja völlig ungeahnte Eigenschaften :thumbsup:
    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!
    Der Vergleich funktioniert auf jeden Fall korrekt. Beides ist Null



    Für mich bleiben Fragen.

    1. Wieso passiert das. In meiner Vorstellung liegen für einen Decimal 16 Bytes im RAM rum. Wenn eine Null rein geschrieben wird, werden die alle Null, vereinfacht gesagt. Wo wird der Unterschied gespeichert?
    2. Wie kann man das Umgehen und eine einfache 0 rein schreiben ohne eine IIf-Abfrage bzw. wie kann man die beiden Darstellungen ineinander umwandeln?
    Bilder
    • IIf-Test.png

      28,05 kB, 828×231, 4.114 mal angesehen

    John422 schrieb:

    In meiner Vorstellung liegen für einen Decimal 16 Bytes im RAM rum.
    Offensichtlich hängt da noch eine Format-Information dran.
    Da müsste man z.B. eine speziell designte Klasse binär serialisieren, um das rauszukriegen.
    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!
    Offensichtlich hängt da noch eine Format-Information dran.
    Es sieht tatsächlich so aus, als hätte ein Decimal-Wert eine Format-Info an Bord, die von der Variable höherer Genauigkeit übernommen wird:
    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!
    Bei einer Gleitkommazahl sind das ja, ich sag mal, tatsächlich Kommazahlen. Deswegen gibts da manchmal diese kleinen Wertverrutschungen, weil nicht jede Kommazahl in so und so vielen Bits existieren kann.
    Ich denke der Decimal Datentyp als Festkommazahl ist in Wahrheit ein Integer, der zusätzlich eine Kommastelle wegspeichert. Quasi 500E-4, 0E-13
    Wenn man mit BigInteger arbeitet, dann bastelt man sowas z.B. selbst, weil es keinen BigDecimal gibt.

    RodFromGermany schrieb:

    Das sind ja völlig ungeahnte Eigenschaften
    Ich find das einen erstaunlichen Bug.
    Zwei gleiche Dinge müssen, wenn sie auf gleiche Weise ausgegeben werden, auch gleich aussehen.
    Double zB macht keine solche Sperenzchen:

    VB.NET-Quellcode

    1. Dim d = 0D, d2 = 0.000D, db = 0.0, db2 = 0.000
    2. MessageBox.Show($"d: {d}, d2: {d2}, db: {db}, db2: {db2}
    3. d = d2: {d = d2}, db = db2: {db = db2}")
    Bilder
    • 2023-12-16 15_11_22-Window.png

      1,66 kB, 178×89, 4.058 mal angesehen

    ErfinderDesRades schrieb:

    Ich find das einen erstaunlichen Bug.
    Da pflichte ich Dir wohl bei. Ich habe gesucht und nix dazu gefunden.
    In C# sieht es genau so aus.
    Vielleicht kann @Löffel was dazu sagen.
    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!
    klar kann man dieselbe Zahl verschieden "darstellen" - und du scheinst mit darstellen eher 'code formulieren' zu meinen.
    Ich sprach aber von Ausgabe. Damit meine ich Ausgabe im allgemeinen, also ob über .ToString formatiert, oder innerhalb einer Serialisierung, oder innerhalb von Dataset.WriteXml oder whatever.
    Wenn der Gleichheits-Operator ergibt, dass zwei Dinge gleich sind, dann soll auch das ausgegebene gleich sein - sofern beides auf dieselbe Weise ausgegeben wird.

    zb bei ausgabe per .ToString: "0" ist nicht das gleiche wie "0.000" - und das darf nicht sein.

    Das ist doch ein grundlegendes logisches Gesetz, dass bei a = b auch gilt: a.ToString = b.ToString

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Oh hm, würde nicht mitgehen, dass das ein "logisches Gesetz" ist, vielleicht ist das ein Gesetz im VB.Net Code, weiß ich nicht.

    Aber ich verstehe sehr wohl, was du meinst.

    Habe auch mal mein Beispiel versucht einzutippern.
    VS nimmt kein 50.00D :huh: , stutzt der so auf 50D.
    Wenn man 50.00 haben möchte muss man 50 + 0.00D schreiben.
    Also die 0 sticht da wirklich raus.

    Gleichzeitig, wenn ich = implementieren müsste, dann guck ich bei String = String einen anderen Algorithmus an als bei Dec = Dec
    Ich denke, was ich sagen möchte ist, ich finde das nicht schlimm, mir gefällts sogar.

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

    0 ist nicht gleich 0.000 (wtf)

    Haudruferzappeltnoch schrieb:

    Oh hm, würde nicht mitgehen, dass das ein "logisches Gesetz" ist
    glaub mir, es ist ein mathematisches Gesetz: Sind zwei Dinge gleich, so sind auch ihre Abbildungen gleich.
    Argumentieren kann ich das schlecht, weil mit logischen Argumenten die Grundlagen der Logik zu begründen - da müssen Leute wie Popper, oder Russel ran - mir wird da glaub zu schnell ein Kreis-Schluss unterlaufen.



    Aber ich habe jetzt herausgefunden, dass sich in .Net 0 tatsächlich von 0.000 unterscheidet:

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Module modMain
    3. Public Sub Main(args As String())
    4. Dim d = 0D, d2 = 0.000D
    5. Dim areEqual = d = d2
    6. Dim bytes = Enumerable.Range(0, 16).Select(Function(x) Marshal.ReadByte(d, x)).ToArray
    7. Dim bytes2 = Enumerable.Range(0, 16).Select(Function(x) Marshal.ReadByte(d2, x)).ToArray
    8. Dim tpls = bytes.Zip(bytes2, AddressOf Tuple.Create).ToArray
    9. Nop() ' Haltepunkt, und tpls angugge
    10. End Sub
    11. End Module
    Der Code liest die 16 Bytes der Decimal-Struktur aus.


    Hier das schockierende Ergebnis:
    Bilder
    • DecimalTester000260.png

      11,04 kB, 286×396, 122 mal angesehen

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Gut, da haben wir nun drei Fachgebiete, die sich sicher alle nicht in alle Punkten einig sind, Mathematik, Informatik und Logik.
    Also Informatisch gilt hier offensichtlich: a=b und a.ToString <> b.ToString.
    Mathematisch gilt: a=b => f(a) = f(b)
    Und logisch gilt damit folglich: ToString ist keine Abbildung.

    Irgendwo muss eine Festkommazahl ja auch die Kommastelle speichern, die Bits können nicht gleich sein.

    Haudruferzappeltnoch schrieb:

    Und logisch gilt damit folglich: ToString ist keine Abbildung.
    eine originelle Folgerung.
    Also .Tostring ist für alle mir bekannten Datentypen eine Abbildung, ausser für den Decimal-Datentyp beim Wert 0.

    Oder liege ich falsch? Gibt es noch weitere Datentypen, wo gelten kann a=b und a.ToString <> b.ToString ?



    Aber in meim Vorpost hatte ich Unrecht: 0 kann durchaus intern verschieden dargestellt werden, weil ist ja egal, wie die Skalierung gesetzt ist - ergibt ja immer 0.
    scheint mir zwar nicht so schlau, intern solche Differenzen zuzulassen, aber ich habs bei dene ja auch nicht zu sagen.

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