AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Nur x Nachkommastellen von Float

Ein Thema von anse · begonnen am 2. Okt 2023 · letzter Beitrag vom 10. Okt 2023
Antwort Antwort
Benutzerbild von anse
anse

Registriert seit: 30. Okt 2006
Ort: Neuenkirchen
196 Beiträge
 
Delphi 11 Alexandria
 
#1

Nur x Nachkommastellen von Float

  Alt 2. Okt 2023, 17:05
Nabend zusammen,

es gibt ja System.Trunc, um den Integer Teil eines Floats zu bekommen.
Gibt es quasi als Gegenstück eine Funktion die nur die ersten Ziffern des Dezimalteils liefert?
Also z.B. sowas
Code:
GetDigits(10.234567, 3); => "234"
Meine Alternative funktioniert auch aber finde ich nicht schön:
  1. Integer-Teil vom Float subtrahieren: 10.234567 - 10 => 0.234567
  2. Ergebnis mit 1000 mulitiplizieren: => 234.567
  3. System.Trunc() darauf: => 234
Ansgar Becker
https://www.heidisql.com
Wenn du loslässt, hast du zwei Hände frei.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.052 Beiträge
 
Delphi 12 Athens
 
#2

AW: Nur x Nachkommastellen von Float

  Alt 2. Okt 2023, 17:29
Punkt 1 ließe sich auch durch Frac(x) ersetzen.
Wenn es Runden statt Abschneiden sein darf, dann wäre RoundTo eine Alternative. Theoretisch kann man vorher mit SetRoundMode einstellen, wie das erfolgen soll (damit ginge auch ein truncate), aber das ist natürlich nicht threadsicher.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
mmw

Registriert seit: 10. Sep 2019
Ort: OWL
324 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Nur x Nachkommastellen von Float

  Alt 2. Okt 2023, 17:57
hallo,
evtl. so (Rohversion)
Delphi-Quellcode:
function GetDigits(Value:EXTENDED;digit:integer):Extended;

var
   value1,
   value2:extended;

begin
 value1:=0;
 value2:=0;
  value1:=frac(value);
  value2:=Power(10,digit);
 result:=trunc(value1*value2);
end;
Gruß
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.052 Beiträge
 
Delphi 12 Athens
 
#4

AW: Nur x Nachkommastellen von Float

  Alt 2. Okt 2023, 21:39
Da digit ein Integer ist, bietet sich auch IntPower an:
Delphi-Quellcode:
function GetDigits(const AValue: Double; Digits: Integer): Integer;
begin
  Result := Trunc(Frac(AValue)*IntPower(10, Digits));
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von anse
anse

Registriert seit: 30. Okt 2006
Ort: Neuenkirchen
196 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Nur x Nachkommastellen von Float

  Alt 3. Okt 2023, 13:10
Vielen Dank, das sieht schon eleganter/lesbarer aus!
Ansgar Becker
https://www.heidisql.com
Wenn du loslässt, hast du zwei Hände frei.
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
744 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Nur x Nachkommastellen von Float

  Alt 8. Okt 2023, 01:40
Double Zahlen sind etwas gefährlich. Die Mantisse bei double ist 52 Bits gross. Wenn ein Dezimalbruch binär geschrieben unendlich viele Stellen hat, dann kann die Mantisse mit ihren 52 Bits unendlich viele der 1en nicht aufnehmen.

Beispiel 0.1(10) ist binär geschrieben periodisch 0.000110011001100....(2) mit Periode 1100. D.h. die Dezimalzahl 0.1 lässt sich als double nicht genau abspeichern. Es werden nur die ersten 52 Bits NACH der ersten 1 (implizites Bit) abgespeichert.

Wenn zum Beispiel genau die ersten 52 Bits der Binärdarstellung eines solchen Bruchs abgespeichert werden, dann ist der effektiv abgespeicherte Wert etwas zu klein (Bits 53+ gehen alle verloren).

Delphi-Quellcode:
procedure testD;
var avalue, d1, d2 : double;
   a,b, res : integer;
begin
  avalue := 98.103;
  d1 := frac(avalue);
  d2 := d1 * 1000;
  res := trunc(d2);
  showmessage(res.ToString);
  showmessage(getdigits(avalue,3).ToString );
end;
wobei GetDigits die weiter oben vorgeschlagene Funktion ist.
Wenn der Code oben in Delphi ausgeführt wird, dann ist d1=0.102999999999994; der Output lautet beide Male 102; wir hätten gern 103.

Was helfen kann:
Wenn man den gespeicherten Wert um den kleinstmöglichen Wert Epsilon = 0 00 00 00 00 00 01 (hex) erhöht, dann liegt im Speicher neu eine etwas zu grosse Zahl. trunc funktioniert dann wie erwartet.

Hinweis: Der Code plusepsilon (unten) kann Plattform abhängig sein und berücksichtigt den Fall "alle 52 Mantissenbits=1" nicht.

Delphi-Quellcode:
function plusepsilon(d: Double): Double;
// addiert die kleinstmögliche zahl zu d.
// Bedingung: d>0
var
  Bits: Int64 absolute d;
begin
  Inc(Bits);
  Result := d;
end;

procedure testD;
var avalue, d1, d2 : double;
   a,b, res : integer;
begin
  avalue := plusepsilon(98.103);
....
(Es gibt natürlich weitere, weniger "mathematische" Lösungen... )
Michael Gasser

Geändert von Michael II ( 8. Okt 2023 um 22:11 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:25 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