Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Nachkommastellen zählen (https://www.delphipraxis.net/52638-nachkommastellen-zaehlen.html)

JayK 31. Aug 2005 18:53


Nachkommastellen zählen
 
Hallo,

wie kann ich in C# die Nachkommastellen einer double-Zahl zählen?
Für meine Zwecke reicht es auch erstmal zu ermitteln, ob die Zahl überhaupt welche hat, oder eine ganze Zahl ist.
Mein Vater meinte, in Delphi macht man dies mit trunc oder so ähnlich. :?
In C# hab ich aber bis jetzt nichts vergleichbares gefunden. :(

Schonmal Danke im voraus
JayK

Khabarakh 31. Aug 2005 19:57

Re: Nachkommastellen zählen
 
Bei Double kannst du die Nachkommastellen durch die Fließkommaungenauigkeit schlecht zählen, da bräuchtest du Decimal (Festkommatyp).
Zitat:

Für meine Zwecke reicht es auch erstmal zu ermitteln, ob die Zahl überhaupt welche hat, oder eine ganze Zahl ist.
Das bestimmst du am besten auch nur näherungsweise:
Code:
public static bool IsInteger(double D)
{
   const Double Epsilon = 1e-6d;
   return D - Math.Floor(D) < Epsilon;
}

JayK 1. Sep 2005 16:55

Re: Nachkommastellen zählen
 
Zitat:

Zitat von Khabarakh
Bei Double kannst du die Nachkommastellen durch die Fließkommaungenauigkeit schlecht zählen, da bräuchtest du Decimal (Festkommatyp).

Ich muss aber double nehmen, weil ich die Zahlen u.a. mit Math.Sqrt() benutze. Und .net weigert sich decimal nach double (oder wars umgekehrt :gruebel:) zu konvertieren. :(

Zitat:

Zitat von Khabarakh
Zitat:

Für meine Zwecke reicht es auch erstmal zu ermitteln, ob die Zahl überhaupt welche hat, oder eine ganze Zahl ist.
Das bestimmst du am besten auch nur näherungsweise:
Code:
public static bool IsInteger(double D)
{
   const Double Epsilon = 1e-6d;
   return D - Math.Floor(D) < Epsilon;
}

Ich könnte das jetzt einfach Copy&Pasten, aber dann weiß ich überhaupt nicht, was in meinem Code vor sich geht :lol:
Wieso sollte man Ganzzahlen "nährungsweise" von anderen rationalen Zahlen unterscheiden? :stupid:

Khabarakh 1. Sep 2005 17:52

Re: Nachkommastellen zählen
 
Zu dem Thema Ungenauigkeit von Fließkommazahlen: hier und hier

Zitat:

Zitat von JayK
Und .net weigert sich decimal nach double (oder wars umgekehrt :gruebel:) zu konvertieren. :(

Delphi-Referenz durchsuchenConvert.ToDouble bzw. Delphi-Referenz durchsuchenConvert.ToDecimal

Zitat:

Zitat:

Zitat von Khabarakh
Zitat:

Für meine Zwecke reicht es auch erstmal zu ermitteln, ob die Zahl überhaupt welche hat, oder eine ganze Zahl ist.
Das bestimmst du am besten auch nur näherungsweise:
Code:
public static bool IsInteger(double D)
{
   const Double Epsilon = 1e-6d;
   return D - Math.Floor(D) < Epsilon;
}

Ich könnte das jetzt einfach Copy&Pasten, aber dann weiß ich überhaupt nicht, was in meinem Code vor sich geht :lol:
Wieso sollte man Ganzzahlen "nährungsweise" von anderen rationalen Zahlen unterscheiden? :stupid:
Code:
double Value = 0.0d;
for (int i = 1; i <= 100; i++)
   Value += 0.01d;
Console.WriteLine(Math.Floor(Value) == Value);
Konsolenausgabe
false

Fließkommazahlen kannst du einfach nicht direkt vergleichen, da es eben z.B. 1 == 1.00000001 oder 1 == 0.999999 heißt. Hier nochmal mein Code, etwas ausführlicher:
Code:
public static bool IsInteger(double D)
{
Das ist dir hoffentlich klar :zwinker: .
Code:
const Double Epsilon = 1e-6d;
Das ist die größte Abweichung, die D von seinem Ganzzahlwert haben darf, dieser Wert wird in der Mathematik mit "Epsilon" bezeichnet ("Sei Epsilon größer Null...").
Code:
return Math.Abs(D - Math.Round(D)) < Epsilon;
Hier gleich eine Verbesserung, hab gestern nur an 1.000001 gedacht :stupid: .
Das gerundete D wird von D abgezogen, im oberen Beispiel wäre das dann -0.0000001 bzw. 0.0000001.
Der Betrag dieser Subtraktion muss nun kleiner als Epsilon sein, damit wir ihn als "ziemlich Ganzzahl" durchlassen.

JayK 1. Sep 2005 19:13

Re: Nachkommastellen zählen
 
Okay, hoffe ich habs einigermaßen verstanden :?
Danke für die Erläuterung ;-)

Und der Vollständigkeit halber zuliebe: Wie siehts bei decimal Zahlen aus mit der Nachkommastellenzählung?

dizzy 1. Sep 2005 21:39

Re: Nachkommastellen zählen
 
Zitat:

Zitat von JayK
Und der Vollständigkeit halber zuliebe: Wie siehts bei decimal Zahlen aus mit der Nachkommastellenzählung?

Was meinst du mit "dezimal"? Dezimal steht nur für Zahlen zur Basis 10, und sagt nichts darüber aus ob sie einen nachkommaanteil besitzen oder nicht.

Typen mit Nachkommaanteil (Beispiele):
Single, Double, Extended, ...

Ohne Nachkommaanteil (Beispiele):
Integer, Word, Byte, Int64, ...

Für alle der oberen Gattung gilt die bereits angesprochene Unmöglichkeit (bzw. nicht in jedem Fall gegebene Möglichkeit) die Nachkommastellen zu zählen, und für alle unteren gilt: Länge des Nachkommaanteils = 0 (per Definition schon ;))
Die einzige Chance die du hättest wäre ein Bei Google suchenFestkommatyp. Diese sind jedoch nicht generisch, und du müsstest sie komplett selbst implementieren oder auf evtl. vorhandere Lösungen zurückgreifen. Diese haben nur das Problem, dass sie meist nur begrenzt genau sind, oder aber einen kleinen Wertebereich besitzen da sie sich intern auf die Typen ohne Nachkommaanteil stützen in der Regel).

Gruss,
Fabian

\\Edit: Und wenn man nun ganz pingelig ist, könnte man behaupten dass eine jede existierende Zahl unendlich viele Nachkommastellen hat. Nur ist in einigen Fällen der größte Teil davon 0 :mrgreen:

Khabarakh 2. Sep 2005 08:27

Re: Nachkommastellen zählen
 
Zitat:

Zitat von dizzy
Zitat:

Zitat von JayK
Und der Vollständigkeit halber zuliebe: Wie siehts bei decimal Zahlen aus mit der Nachkommastellenzählung?

Was meinst du mit "dezimal"? Dezimal steht nur für Zahlen zur Basis 10, und sagt nichts darüber aus ob sie einen nachkommaanteil besitzen oder nicht.

In C# ist schon ein Typ implementiert, mit dem sich Dezimalzahlen exakt darstellen lassen. Sein Name: decimal :wink: .
Zur Zählung der Nachkommastellen wäre es wahrscheinlich am besten, mit "unsafe code"die Variable in Mantisse und Exponent zu zerlegen, das Ergebnis müsste dann "Anzahl von Nicht-Null-Stellen der Mantisse von links - Exponent" oder so ähnlich sein. Allerdings gibt es nicht einmal in Hejlsbergs Buch eine genaue Beschreibung der decimal-Struktur.

dizzy 2. Sep 2005 09:52

Re: Nachkommastellen zählen
 
Zitat:

Zitat von Khabarakh
In C# ist schon ein Typ implementiert, mit dem sich Dezimalzahlen exakt darstellen lassen. Sein Name: decimal :wink: .

:oops:

Zitat:

Zitat von Khabarakh
Zur Zählung der Nachkommastellen wäre es wahrscheinlich am besten, mit "unsafe code"die Variable in Mantisse und Exponent zu zerlegen, das Ergebnis müsste dann "Anzahl von Nicht-Null-Stellen der Mantisse von links - Exponent" oder so ähnlich sein. Allerdings gibt es nicht einmal in Hejlsbergs Buch eine genaue Beschreibung der decimal-Struktur.

Ich glaube auch nicht, dass decimal in einem Float-Format mit Mantisse und Exponent hinterlegt ist, weil dann wäre die Darstellung eben nicht mehr "exakt" möglich ;). Ich nehme daher an, dass es sich um eine fertige Implementierung eines Festkommatyps handelt, oder einen Float der in seinem Wertebereich zugunsten der Genauigkeit beschnitten ist, und eine max. Nachkommastellenanzahl kleiner der möglichen Genauigkeit definiert. Wobei ich bei letzterem auch bezweifle dass die Darstellung damit immer "exakt" möglich ist.

Um also das Problem abschließend lösen zu können wäre eine Doku zum Aufbau von decimal nicht schlecht :)

JayK 24. Sep 2005 20:32

Re: Nachkommastellen zählen
 
Aufbau? Damit kann ich nicjh dienen :?
Ich hab aber rausgefunden: Decimal kann auch nur 28 Stellen (nicht Nachkommastellen) darstellen. Heißt aber trotzdem Festkommatyp :?

Weiß aber immer noch nich, wie ich die Nachkomastellen von Decimal zählen kann... :-(

Und weil ich vergessen habe, eine Sprache für den Thread festzulegen, möchte ich gerne noch wissen, wie man das mit Extended unter Delphi macht :mrgreen:
Die Funktion von Khabarakh hat ja ordentlich funktioniert, wie würde die in Delphi aussehen? :?
Delphi-Quellcode:
const Double Epsilon = 1e-6d;
Bei dem d hapert's. Das e nimmt er sogar schon an. :) (Ob richtig oder falsch weiß ich nich)

Khabarakh 24. Sep 2005 21:30

Re: Nachkommastellen zählen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von JayK
Ich hab aber rausgefunden: Decimal kann auch nur 28 Stellen (nicht Nachkommastellen) darstellen. Heißt aber trotzdem Festkommatyp :?

:gruebel: ? Irgendwo muss schon eine Grenze sein :wink: (oder programmiert Hagen schon unter .NET :mrgreen: ?) .

Zitat:

Und weil ich vergessen habe, eine Sprache für den Thread festzulegen, möchte ich gerne noch wissen, wie man das mit Extended unter Delphi macht :mrgreen:
Die Funktion von Khabarakh hat ja ordentlich funktioniert, wie würde die in Delphi aussehen? :?
Delphi-Quellcode:
const Double Epsilon = 1e-6d;
Bei dem d hapert's. Das e nimmt er sogar schon an. :) (Ob richtig oder falsch weiß ich nich)
Literale in Delphi haben keine "Kennung":
Delphi-Quellcode:
const Epsilon = 1E-6;
Fäst hätte ich vergessen, dass ich vor einer Woche ein Programm zum Auseinandernehmen von Decimal geschrieben habe:
Code:
                public static unsafe byte[] GetBytes(void* p, uint Length)
      {
         byte[] Bytes = new byte[Length];
         byte* bytep = (byte*) p;
         for (int i = 0; i < Length; i++) {
            Bytes[i] = *bytep;
            bytep++;
         }
         return Bytes;
      }
Für alle ohne Framework ein paar Ergebnisse:
Code:
1 =

Byte 0: 00000000 0
Byte 1: 00000000 0
Byte 2: 00000000 0
Byte 3: 00000000 0
Byte 4: 00000000 0
Byte 5: 00000000 0
Byte 6: 00000000 0
Byte 7: 00000000 0
Byte 8: 10000000 1
Byte 9: 00000000 0
Byte 10: 00000000 0
Byte 11: 00000000 0
Byte 12: 00000000 0
Byte 13: 00000000 0
Byte 14: 00000000 0
Byte 15: 00000000 0
Code:
1,00 =

Byte 0: 00000000 0
Byte 1: 00000000 0
Byte 2: 01000000 2
Byte 3: 00000000 0
Byte 4: 00000000 0
Byte 5: 00000000 0
Byte 6: 00000000 0
Byte 7: 00000000 0
Byte 8: 00100110 100
Byte 9: 00000000 0
Byte 10: 00000000 0
Byte 11: 00000000 0
Byte 12: 00000000 0
Byte 13: 00000000 0
Byte 14: 00000000 0
Byte 15: 00000000 0
Code:
-1,000000000000000000000 =

Byte 0: 00000000 0
Byte 1: 00000000 0
Byte 2: 10101000 21
Byte 3: 00000001 128
Byte 4: 01101100 54
Byte 5: 00000000 0
Byte 6: 00000000 0
Byte 7: 00000000 0
Byte 8: 00000000 0
Byte 9: 00000000 0
Byte 10: 00000101 160
Byte 11: 01111011 222
Byte 12: 10100011 197
Byte 13: 10110101 173
Byte 14: 10010011 201
Byte 15: 10101100 53
Sollte man die Bits noch umdrehen? So sollte es aber stimmen:
Code:
Byte 0-1: Unbenutzt
Byte   2: Exponent in Byte, 0 <= e <= 28
Byte   3: Vorzeichen, 128 = Negativ
Byte 4-7: 16 Bit Ganzzahl, 2. Teil der Mantisse
Byte 8-15: 32 Bit Ganzzahl, 1. Teil der Mantisse


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz