Ankündigung

Einklappen
Keine Ankündigung bisher.

Veränderung der Nachkommastelle einer Fließkommazahl

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Veränderung der Nachkommastelle einer Fließkommazahl


    Hallo,

    ich benötige und erstellte - dachte ich - eine Funktion, welche den Nachkommawert einer beliebigen Zahl auf x.5 ändert.
    Aus z.B. 1.0 bis 1.9 einschließlich soll 1.5 werden. Ebenso aus z.B. -1 bis -1.9 soll -1.5 werden.

    Meine Funktion:

    Code:
    float toPointFive(float wert)
            {
                int x = (int) wert;
    
                if (wert < 0.0f)
                {
                    x = Math.Abs(x);
                    wert = x + 0.5f;
                    wert = wert * -1f;
                }
                else
                {
                    wert = x + 0.5f;
                }
                return wert;
            }

    Bei allen negativen Zahlen mit .0 als Nachkommastelle tritt ein Fehler auf.
    Aus -3.0 wird nicht, wie gewünscht, -3.5 sondern -2.5, aus -2.0 wird -1.5.
    -3.1 bis -3.9 werden zu -3.5, nur -3.0 nicht.

    Habt Ihr eine Idee, woran das liegen mag?
    Ich weiß jedenfalls nicht mehr weiter.

    Vielen Dank für Eure Hilfe.

  • #2
    Hallo!

    Dein Code ist etwas aufwendig für die gewünschte Aufgabe, aber ich kann keinen Fehler erkennen.

    Probeweise habe ich den Code laufen lassen.

    https://dotnetfiddle.net/

    Bei Übergabe von -3.1f erhalte ich das, was du willst, nämlich -3.5. Bei -2.0 erhalte ich -2.5.

    Ich kann also nicht nachvollziehen, wo du ein Problem hast?

    cu

    Kommentar


    • #3
      Hallo,

      Danke für deine Antwort.
      Bei allen negativen Zahlen mit .0 als Nachkommastelle tritt ein Fehler auf.
      Der Fehler tritt auf, wenn die Zahl z.B. -3.0 ist.

      Ich habe erst nach dem Stellen meiner Frage in diesem Forum erfahren, dass das Problem in diesem Falle daran lag, dass ich eine Schleife der Art

      Code:
      for( float fx = -4.0f fx < 0.0f; fx += 0.1f)
      {
      float fy = 
      toPointFive(fx); }


      benutzte.

      Darin soll per se ein Rundungsfehler stecken.
      Dabei geschieht dann, dass x in der Schleife den Wert -2.99999 anstelle von -3.0 besitzt und das von mir beschriebene Problem auftritt, also -2.5 anstelle von -3.5, was dann nachvollziehbar ist, da -2.999 gekürzt um ihre Nachkommastellen eben -2 und nicht -3 ist.
      Wenn du magst, kannst du es mal ausprobieren.

      Hast du denn eine Idee, wie ich dieses Problem umgehen kann?

      Ich kann nur float benutzen.
      Wie kann ich diese sicher in x.5 verändern? Also -3.0 bis -3.9 wird zu -3.5 und nicht, wie jetzt bei -3.0, zu -2.5?
      Floor, Ceiling und Truncate funktionieren auch nicht zuverlässig.

      Ich bin für jede Anregung dankbar.

      Ach so, den Code hatte ich später "einfach so" zu Testzwecken erstellt...

      Kommentar


      • #4
        Hallo!

        Auch mit der Schleife kann ich dein Problem nicht reproduzieren.

        Bitte poste doch einmal den vollständigen Code, sonst wird das hier zum Rätselraten.

        Das ein Rundungsfehler auftritt, war von Anfang an naheliegend.

        Float ist nunmal nur 4 Byte groß und kann eine Nachkommastelle nicht unendlich genau darstellen. Double ist mit 8 Byte schon deutlich größer und damit genauer, aber auch dort treten Rundungsfehler auf, die prinzipieller Natur sind.

        Es ist nunmal so, dass ein Float oder auch ein Double intern als Binärzahl dargestellt werden. Die Umwandlung von Dezimal- in das Binärsystem ist nicht exakt. Das bedeutet, dass Zahlen, die im Dezimalsystem endlich sind, im Binärsystem unendlich sein können und umgekehrt.

        Deshalb funktioniert auch das hier nicht.

        Code:
        if((0.1f + 0.2f) == 0.3f)
        {
                Console.WriteLine("Ich werde nicht ausgegeben.");
        }
        Hier findest du die genaue Erklärung zu dem Thema.

        https://csharpindepth.com/Articles/FloatingPoint

        Die einzige Lösung wäre, dass du Dezimalzahlen verwendest!

        Dazu gibt es in C#/.NET die Klasse System.Decimal.

        https://csharpindepth.com/articles/Decimal

        cu
        Zuletzt geändert von StarShaper; 24.08.2019, 13:24.

        Kommentar

        Lädt...
        X