Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Delphi & Runden (https://www.delphipraxis.net/140290-delphi-runden.html)

Blup 15. Sep 2009 16:16

Re: Delphi & Runden
 
Du könntest zur Laufzeit an der Adresse der Round-Funktion einen Sprung in deine eigene Round-Funktion patchen.

brechi 16. Sep 2009 07:55

Re: Delphi & Runden
 
@Blup: ist mir dafür zu aufwändig.

Hier nochmal der Code falls jemand bisl testen will:

Delphi-Quellcode:
program RoundTest;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  db,
  dbtables;

var
  Table: TTable;
  DbaseFile: string;
  Temp: array[0..255] of char;

  Def: TFieldDef;

  Values: array[0..7] of Double = (2.5, 3.5, 2.2, 2.8, 2.25, 2.35, 2.22, 2.28);
  ValuesWanted: array[0..7] of Double = (3, 4, 2, 3, 2.3, 2.4, 2.2, 2.3);
  i: Integer;
begin
  if GetTempPathA(SizeOf(Temp), Temp) > 0 then begin
    DbaseFile := IncludeTrailingPathDelimiter(Temp) + 'test1234.dbf';
    Table := TTable.Create(nil);
    Table.TableType := ttDBase;
    Table.TableLevel := 4;
    Table.TableName := ExtractFileName(dBaseFile);
    Table.DatabaseName := ExtractFilePath(DbaseFile);

    Def := Table.FieldDefs.AddFieldDef;
    Def.Name := 'Feld';
    Def.DataType := ftBCD;
    Def.Precision := 5; // Delphi vertauscht Precision und Size
    Def.Size := 1;

    Table.CreateTable;
    Table.Open;
    for i := Low(Values) to High(Values) do begin
      Table.Append;
      if i < 4 then
        Table['Feld'] := Round(Values[i])
      else
        Table['Feld'] := Values[i];
      Table.Post;
    end;

    Table.First;

    for i := Low(Values) to High(Values) do begin
      if i < 4 then
        Writeln(Format('Format: %0.0f', [Values[i]]), ' Round: ', Table['Feld'], ' wanted: ', FloatToStr(ValuesWanted[i]))
      else
        Writeln(Format('Format: %0.1f', [Values[i]]), ' Table: ', Table['Feld'], ' wanted: ', FloatToStr(ValuesWanted[i]));

      Table.Next;
    end;
    Table.Close;
    Table.Free;

    ReadLn;
  end;
end.
Schade, dass intern bei Variant konvertierung nicht Format verwendet wird, das liefert immer das "richtige" Ergebnis.

Toll ist übrigens auch, dass bei der Verwendung von z.B. rmUpals RoundMode in Delphi bei der Optimierung nicht verwendet wird.

Delphi-Quellcode:
SetRoundMode(rmUp)
Caption := IntToStr(Round(2.5));
liefert eine 2, da durch die Optimierung die Konstante schin intern auf 2, mit dem rmNearest Verfarhen gerundet wird...

brechi 16. Sep 2009 08:17

Re: Delphi & Runden
 
Zusatzinfo:

RoundTo und SimpleRoundTo liefern auch sehr komishce Werte:

SimpleRoundTo(3.5,0) liefert 4 (wie gewünscht, rundet also auf)
SimpleRoundTo(3.35,-1) liefert 3.3 (rundet ab)

brechi 16. Sep 2009 10:32

Re: Delphi & Runden
 
Meine Lösung:

Delphi-Quellcode:

// uses BDE, Math;

// auf Nachkommastellen runden
function RoundNumber(_Value: Extended;
  _Prec: Integer): Extended;
begin
  Result := Trunc(Abs(_Value) * Power(10, _Prec) + 0.5) / Power(10, _Prec) * Sign(_Value);
end;

// Feld in Tabelle setzen
procedure SetNumber(_Table: TTable; _Field: string;
  _Number: Extended);
begin
  _Table[_Field] := RoundNumber(_Number, GetPrec(_Table, _Field));
end;

// Feld aus Tabelle auslesen
function GetNumber(_Table: TTable;
  _Field: string): Extended;
begin
  Result := RoundNumber(_Table[_Field], GetPrec(_Table, _Field));
end;

// da Table.FieldDef.Size und Precision nicht die Nachkommastellen liefert (unoptimiert):

function GetPrec(_Table: TTable; _Field: string): Integer;
var
  FldsArr: array of FLDDesc;
  i: Integer;
begin
  Result := 0;
  SetLength(FldsArr, _Table.FieldCount + 1);
  Check(DbiGetFieldDescs(_Table.handle, @FldsArr[0]));
  for i := Low(FldsArr) to High(FldsArr) do
    if SameText(FldsArr[i].szName, _Field) then
      Result := FldsArr[i].iUnits2;
end;

stho 16. Sep 2009 10:47

Re: Delphi & Runden
 
Ist vielleicht nicht die beste Methode, aber immerhin wurde sie noch nicht genannt (außer ich habs net gesehen):

Delphi-Quellcode:
Ergebniss := Zahl1 div Zahl2;
Ergebniss muss aber Integer sein.

Verbessert mich wenn ich falsch liege ;-) Arbeite erst seit 7-8 Wochen mit Delphi

DeddyH 16. Sep 2009 10:49

Re: Delphi & Runden
 
Dann würde ja immer abgerundet ;)

P.S.: Willkommen in der DP :dp:

himitsu 16. Sep 2009 11:30

Re: Delphi & Runden
 
Delphi-Quellcode:
gerundetesErgebniss := (Zahl1 + (Zahl2 div 2)) div Zahl2;
Aber das Löst ja nicht das Problem hier ... vorallem nicht vei den Variants, wo intern gerundet wird.

Eventuell könnte man da die internen Funktionen der Variants hooken und dort seine eigene Roundmethode einschleusen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:58 Uhr.
Seite 2 von 2     12   

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