Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Runden ohne nachfolgende Nullen (https://www.delphipraxis.net/191987-runden-ohne-nachfolgende-nullen.html)

Rollo62 10. Mär 2017 16:53

Runden ohne nachfolgende Nullen
 
Hallo zusammen,

ich wollte die nachfolgenden Nullen einer Zahl abschneiden, und
nach ein bischen rumgerechne hab ich es aber aufgegeben das mit Mathematik zu lösen,
und habs dann doch wieder mit String-Operationen in einer Schleife gelöst.
War wohl schon zu müde und hatte zu wenig Zeit.

Aber trotzden würde mich interessieren wie man das am elegantester löst:

Ich möchte Fließkommazahlen auf z.B. 3-nachkommastellen runden, und als String
formatieren.
Z.B. mit
Delphi-Quellcode:
LTxt := Format('%1.3f', [ dblNumber]);
.

Da kommt dann z.B. das raus:
1,234
2,404
2,001
1,000
1,100
1,403
2,330

Aber dann möchte ich die training Zero's löschen:

1,234 --> 1,234
2,404 --> 2,404
2,001 --> 2,001
1,000 --> 1
1,100 --> 1,1
1,040 --> 1,04
2,330 --> 2,33

Mit String-Operationen geht das, aber es sollte doch auch einen mathematischen Weg
Geben, so ala
Delphi-Quellcode:
RoundTo(dblNumber, -3);
?

Wie würdet Ihr das machen ?

Rollo

mkinzler 10. Mär 2017 17:08

AW: Runden ohne nachfolgende Nullen
 
Das ist ja eher eine Anzeigeproblem. Im Speicher unterscheidet sich 1 und 1,000 ja nicht.

Andidreas 10. Mär 2017 17:26

AW: Runden ohne nachfolgende Nullen
 
Hi,

was stört dich an Funktionen wie FloatToStr oder FloatToStrF ?

Rollo62 10. Mär 2017 18:16

AW: Runden ohne nachfolgende Nullen
 
Ich möchte keine festen Nachkommastellen, sondern die nachfolgenden Nullen löschen.

Das geht ja wie gesagt als String-Schleife, von hinten nach vorne, alles was Null oder Komma ist Löschen bis was anderes kommt.

Jedenfalls kan ich nicht z.B. im Format() die Stellen VOR der Konvertierung ändern,
sondern ich möchte es automatisch am Ergebnis raushaben.
Oder eben besser das die Nullen gar nicht erst entstehen.

Wenn ich die z.B. die Funktion
Delphi-Quellcode:
Format ('%*.*f', [LPre, LPost, 123.456]);
benutze, dann wäre eine Formel für LPost nicht schlecht,
welche wiederung von der Zahl selbst abhängt: also
1.234 --> LPost = 3 (relevante Nachkommas)
1.230 --> LPost = 2 (relevante Nachkommas)
1.200 --> LPost = 1 (relevante Nachkommas)

Wie könnte man LPost aus der FloatZahl berechen ?

Rollo

Tyrolean 10. Mär 2017 18:33

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von Rollo62 (Beitrag 1363756)
1,100
Rollo

Formatfloat('#,##0.###',1.1);

Sollte doch das machen?

hanvas 10. Mär 2017 19:48

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von Rollo62 (Beitrag 1363756)
Hallo zusammen,

Wie würdet Ihr das machen ?

Rollo

Code:
function makeStr(d : Double) : String;
var l,c : Integer;
begin
 result := IntToStr(Trunc(d * 1000));
 l     := Length(result);
 c     := 0;
 while (result[l-c] = '0') and
       (c<3) do
             c := c + 1;
 if (c>0) then // bis ende löschen
     Delete(result,l-c,l);
 if (c<3) then
     insert(',',result,l-c);
end;
ungetestet

cu Ha-Jö

EWeiss 10. Mär 2017 21:06

AW: Runden ohne nachfolgende Nullen
 
Ein inc(c) tut's auch.

gruss

hanvas 10. Mär 2017 21:19

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von EWeiss (Beitrag 1363768)
Ein inc(c) tut's auch.

gruss

Aus welchen Grund sollte ich inc verwenden? Das inc und dec scheller ist als +1/-1 halte ich für einen Mythos.

cu Ha-Jö

EWeiss 10. Mär 2017 21:27

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von hanvas (Beitrag 1363769)
Zitat:

Zitat von EWeiss (Beitrag 1363768)
Ein inc(c) tut's auch.

gruss

Aus welchen Grund sollte ich inc verwenden? Das inc und dec scheller ist als +1/-1 halte ich für einen Mythos.

cu Ha-Jö

Hat niemand verlangt nur das es auch tut ;)
Allerdings ist das Konzept schon seit 1969 bekannt und scheint in 2017 noch nicht angekommen zu sein.

https://en.wikipedia.org/wiki/Increm...ment_operators

gruss

juergen 10. Mär 2017 21:42

AW: Runden ohne nachfolgende Nullen
 
Hallo,

meine Delphi-Version kann das (leider) noch nicht, du könntest aber die TStringHelper nutzen.
Ich würde das dann so machen:

Delphi-Quellcode:
s := s.TrimRight([#048, #044]);

Edit: 800. :-) :party:

Uwe Raabe 10. Mär 2017 23:10

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von hanvas (Beitrag 1363769)
Aus welchen Grund sollte ich inc verwenden? Das inc und dec scheller ist als +1/-1 halte ich für einen Mythos.

Der Compiler erzeugt eh für beides denselben Code.

t.roller 11. Mär 2017 07:43

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von juergen (Beitrag 1363772)
Hallo, meine Delphi-Version kann das (leider) noch nicht, du könntest aber die TStringHelper nutzen.
Ich würde das dann so machen:

Delphi-Quellcode:
s := s.TrimRight([#048, #044]);

Man sollte aber den Punkt (#46) am Ende auch entfernen:
Delphi-Quellcode:
s := s.TrimRight([#048, #044, #46]);

Ghostwalker 11. Mär 2017 07:43

AW: Runden ohne nachfolgende Nullen
 
Warum was selber schreiben, wenn es das doch schon gibt.

FloatToStr tut genau das was du möchtest.

BSP.:

Delphi-Quellcode:
const
   cFloats : array[0..6] of double = (
1.234,2.404,2.001,1.000,1.100,1.403,2.330);
{$R *.dfm}

procedure TForm71.TntButton1Click(Sender: TObject);
var
  i : integer;

begin
  log.Lines.Clear;
  for I := 0 to 6 do
  begin
    log.Lines.Append(format('%1.3f',[cFloats[i]])+' = '+floatToStr(cFloats[i]));
  end;
end;
Ergebnis:


Code:
1,234 = 1,234
2,404 = 2,404
2,001 = 2,001
1,000 = 1
1,100 = 1,1
1,403 = 1,403
2,330 = 2,33

t.roller 11. Mär 2017 07:48

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von Ghostwalker (Beitrag 1363786)

Bill Gates, 1981: "640K sollte genug für jedermann sein".

640k: Ja, als Monatseinkommen, egal ob Dollar oder Euro.

Ghostwalker 11. Mär 2017 08:10

AW: Runden ohne nachfolgende Nullen
 
Da stimm ich dir zu. Leider bezog er sich damals auf den Hauptspeicher eines Rechners.

himitsu 11. Mär 2017 09:08

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1363777)
Der Compiler erzeugt eh für beides denselben Code.

Außer bei Properties, wo der Compilier auch nicht schlau genug ist das mit Inc (Pascal) umsetzen zu lassen. :angle:

Aber ja,
Delphi-Quellcode:
Variable := Variable + 1;
wird vom Compiler zu einem INC optimiert.
Letztendlich ist es egal was man nimmt, aber man kann so einen Code kürzer und übersichtlicher gestalten.

Uwe Raabe 11. Mär 2017 10:51

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von himitsu (Beitrag 1363795)
Außer bei Properties, wo der Compilier auch nicht schlau genug ist das mit Inc (Pascal) umsetzen zu lassen. :angle:

Leider funktioniert
Delphi-Quellcode:
Inc(<Property>)
aber auch nicht. :angle:

EWeiss 11. Mär 2017 11:35

AW: Runden ohne nachfolgende Nullen
 
Zitat:

aber man kann so einen Code kürzer und übersichtlicher gestalten.
Und man erkennt wer den sinn einer Programmierung verstanden hat.

Wenn ich nen Audi will nehme ich keinen GOGO.
Von Quelltexten welche solche (sichtbaren) Implementierungen verwenden nehme ich persönlich abstand.
Wäre ein Rückschritt zu VB6 :) Auch wenn ich es noch heute verwende.

Aber ja jeder wie er will.

gruss

kwhk 11. Mär 2017 12:59

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von mkinzler (Beitrag 1363757)
Ich möchte Fließkommazahlen auf z.B. 3-nachkommastellen runden, und als String formatieren.

FloatToString beseitig zwar alle Vornullen und Nachkommanullen, es fehlt aber das Runden auf drei Nachkommastellen.
Delphi-Quellcode:
const
  cFloats : array[0..6] of double = (1.2347,
                                     2.4043,
                                     2.001,
                                     1.0002,
                                     1.100123,
                                     1.4036,
                                     2.330456);
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
   i : integer;
begin
   log.Lines.Clear;
   for I := 0 to 6 do
   begin
     log.Lines.Append(format('%1.3f',[cFloats[i]])+' = '+floatToStr(cFloats[i]));
   end;
end;
Code:
1,235 = 1,2347
2,404 = 2,4043
2,001 = 2,001
1,000 = 1,0002
1,100 = 1,100123
1,404 = 1,4036
2,330 = 2,330456

Uwe Raabe 11. Mär 2017 13:15

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von kwhk (Beitrag 1363819)
FloatToString beseitig zwar alle Vornullen und Nachkommanullen, es fehlt aber das Runden auf drei Nachkommastellen.

Dann vielleicht so?
Delphi-Quellcode:
program Project213;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Math;

const
  cFloats: array [0..6] of double = (1.2347, 2.4043, 2.001, 1.0002, 1.100123, 1.4036, 2.330456);

var
  d: double;

begin
  for d in cFloats do begin
    Writeln(format('%1.3f = %s', [d, FloatToStr(RoundTo(d, -3))]));
  end;
  Readln;
end.
Code:
1,235 = 1,235
2,404 = 2,404
2,001 = 2,001
1,000 = 1
1,100 = 1,1
1,404 = 1,404
2,330 = 2,33

Rollo62 11. Mär 2017 14:54

AW: Runden ohne nachfolgende Nullen
 
Ja Dankeschön an Alle.

Trim ist eine Alternative aber das löscht auch nur die Zeichen weg.
Die wollte ich gar nicht erst erzeugen um dann zu löschen.
Darum gings mir ja, die Nullen gar nicht erst erzeugen.

Formatierung mit Runden geht in die Richtung was ich Suche.
Muss ich checken, denke aber das wird ok sein.

Rollo

Andidreas 13. Mär 2017 11:36

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1363821)
Zitat:

Zitat von kwhk (Beitrag 1363819)
FloatToString beseitig zwar alle Vornullen und Nachkommanullen, es fehlt aber das Runden auf drei Nachkommastellen.

Dann vielleicht so?
Delphi-Quellcode:
program Project213;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Math;

const
  cFloats: array [0..6] of double = (1.2347, 2.4043, 2.001, 1.0002, 1.100123, 1.4036, 2.330456);

var
  d: double;

begin
  for d in cFloats do begin
    Writeln(format('%1.3f = %s', [d, FloatToStr(RoundTo(d, -3))]));
  end;
  Readln;
end.

Wenn er das "Bankers Rounding" verwenden möchte, dann so...
Ansonsten sei auch noch der Hinweis auf die Funktion von shmia erlaubt --> http://www.delphipraxis.net/50081-ka...ch-runden.html

Ghostwalker 13. Mär 2017 13:15

AW: Runden ohne nachfolgende Nullen
 
@Andidreas

Ähmm......also..entweder stimmt Wikipedia nicht oder Emba hat da nen Bug :)

RoundTo(2.3500,-1) ergibt 2.3 lt. Wiki sollte das aber 2.4 ergeben :)

Deshalb hab ich mir mal folgende Rundung gebaut:

Delphi-Quellcode:
TYPE
  TRoundAlg = (raKfm,raSience);

function Rounder(alg:TRoundAlg;value:extended;decimalplaces:integer):extended;

implementation



function Rounder(alg:TRoundAlg;value:extended;decimalplaces:integer):extended;
var
  pre,nex,tmp : extended;
  pt : extended;
  hlp : integer;

begin
  pt := power(10.0,decimalplaces);
  pre := int(value*pt);
  nex := frac(value*pt);
  case alg of
    raKfm: begin
            if (nex >= 0.5) then pre := pre+1.0;
            result := pre/pt;
    end;
    raSience: begin
                if (nex > 0.50) then pre := pre+1.0;
                if (nex = 0.5) then
                begin
                  tmp := Frac(pre/10)*10;
                  hlp := round(tmp);
                  if (hlp in [1,3,5,7,9]) then
                    pre := pre+1.0;
                end;
                result := pre/pt;
    end;
  end;

end;
Damit funzt es so wie es im Wiki beschrieben ist :)

Andidreas 13. Mär 2017 13:38

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von Ghostwalker (Beitrag 1364024)
@Andidreas

Ähmm......also..entweder stimmt Wikipedia nicht oder Emba hat da nen Bug :)

RoundTo(2.3500,-1) ergibt 2.3 lt. Wiki sollte das aber 2.4 ergeben :)


Damit funzt es so wie es im Wiki beschrieben ist :)

Was für ne Delphi Version hast Du?
In Delphi 10.1 Update 2 bekomme ich bei

Delphi-Quellcode:
RoundTo(2.3500, -1)
wie erwartet 2.4 als Ergebnis ;-)

Ghostwalker 13. Mär 2017 14:28

AW: Runden ohne nachfolgende Nullen
 
Zitat:

Zitat von Andidreas (Beitrag 1364028)
Zitat:

Zitat von Ghostwalker (Beitrag 1364024)
@Andidreas

Ähmm......also..entweder stimmt Wikipedia nicht oder Emba hat da nen Bug :)

RoundTo(2.3500,-1) ergibt 2.3 lt. Wiki sollte das aber 2.4 ergeben :)


Damit funzt es so wie es im Wiki beschrieben ist :)

Was für ne Delphi Version hast Du?
In Delphi 10.1 Update 2 bekomme ich bei

Delphi-Quellcode:
RoundTo(2.3500, -1)
wie erwartet 2.4 als Ergebnis ;-)

Okok...meine ist (noch) alt :))


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:51 Uhr.

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