Fliesskommazahlen und Ungenauigkeiten

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1436
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Fliesskommazahlen und Ungenauigkeiten

Beitrag von fliegermichl »

Das Thema hatten wir schon öfter und die Antwort war meistens, daß ich Festkommazahlen verwenden soll.
Einzig was bislang noch nicht geklärt wurde ist: Wie geht das?

Wenn ich folgenden Codeschnipsel laufen lasse und 0,2 in das Eingabefeld eingebe, dann kommt 204,8 bei raus. Das ist für mich vollkommen unbrauchbar.
Die Typen Single und Double müssten eigentlich ungenau und halbsoungenau heissen.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var d : Double;
    i : integer;
begin
 d := StrToFloat(edEingabe.Text);
 for i := 1 to 10 do
   d := d + d;
 edAusgabe.Text := FloatToStr(d);
end;
Man kann diese Abweichungen auch sehr schön z.B. hier sehen.

Kann man evtl. auch eine solche Bibliothek wie hier dafür verwenden?

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von siro »

Guten Morgen,
fehlt da evtl. noch ein Kaffee :wink:

Das ist doch richtig:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
  var d : Double;
      i : integer;
begin
   d := 0.2;
   for i := 1 to 10 do begin
     d := d + d;
     ListBox1.items.add(FloatToStr(d));
   end;
   caption:= FloatToStr(d);
end;
Reihe.png
Reihe.png (4.18 KiB) 3476 mal betrachtet
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1436
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von fliegermichl »

Guten Morgen.

Kaffee, ich brauche mehr Kaffee :-)

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 338
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon (Windows wenn notwendig), Lazarus 3.0 FPC 3.3.1

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von Niesi »

Solche Irrtümer können einfach vermieden werden, wenn die Berechnungen zur Kontrolle auch noch mal mit einer Tabelle in Calc gecheckt werden.
Mache ich grundsätlich so, auch wenn die Tabellen bei mir dann schon mal sehr umfangreich werden ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6217
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von af0815 »

fliegermichl hat geschrieben:
Di 19. Dez 2023, 06:04
Das Thema hatten wir schon öfter und die Antwort war meistens, daß ich Festkommazahlen verwenden soll.
Einzig was bislang noch nicht geklärt wurde ist: Wie geht das?
Ich glaube da wurdest du in Richtung https://wiki.freepascal.org/Currency/de geschubst. Nur der Typ ist mir unheimlich, wirklich arbeiten kann man damit nicht :-) Zumindest habe meine paar Versuche darinnen geendet, das ich mir den größten Integertyp genommen habe und das Komma verschoben habe, damit das für mich passt. Aber auch da kämpfst du mit den Rundungen.

Wir haben da ja einige die sich mit WaWi beschäftigen, wie löst ihr das in euren Programmen ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

hum4n0id3
Beiträge: 301
Registriert: So 5. Mai 2019, 15:23

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von hum4n0id3 »

Niesi hat geschrieben:
Di 19. Dez 2023, 08:36
Solche Irrtümer können einfach vermieden werden, wenn die Berechnungen zur Kontrolle auch noch mal mit einer Tabelle in Calc gecheckt werden.
Mache ich grundsätlich so, auch wenn die Tabellen bei mir dann schon mal sehr umfangreich werden ...
Oder man schreibt Tests.

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von Mathias »

Das schlimmste finde ich das hier, das komisch Runden. Wegen diesem Mist habe ich mir mal einen ganzen Tag die Zähne ausgebissen.
Wir hatten mal in der Schule gelernt, als über 0.5 wird aufgerundet.
Ich wurde dann belernt, das die für die Bürolisten gemacht wurde, wen sie mit Geld rechnen.
Aber für Vektorberechnungen ist dies unbrauchbar.

Code: Alles auswählen

var
  f:Single=0.5;
  i: Integer;
begin
  Memo1.Clear;;
  for i:=0 to 7 do begin
    Memo1.Lines.Add(Round(f).ToString);
    f:=f+1.0;
  end;       
Ausgabe:

Code: Alles auswählen

0
2
2
4
4
6
6
8
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1436
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von fliegermichl »

In meinem CAD Programm habe ich tatsächlich ziemliche Probleme mit diesen Ungenauigkeiten.
Ich habe mir dieses MPArith mal angeschaut aber da werde ich nicht wirklich schlau draus.

Es gibt auch GNUMP zum beliebig genauen rechnen aber da muß man studiert haben um zu schnallen wie das funktioniert.

siro
Beiträge: 732
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von siro »

Das übliche bzw. frühere Runden, wie ich es gelernt habe und auch in Turbo Pascal war,
gibt es in FPC garnicht mehr.... :( (zumindest mir nicht bekannt wie ich das einstellen kann....)
Für Zeichenoperationen nutze ich:

Code: Alles auswählen

function XRound(Num:Double):Integer;
begin
  if Num >=0 then result:=Trunc(num+0.5)
             else result:=Trunc(num-0.5);
end;           
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von Mathias »

Das übliche bzw. frühere Runden, wie ich es gelernt habe und auch in Turbo Pascal war,
gibt es in FPC garnicht mehr.... :( (zumindest mir nicht bekannt wie ich das einstellen kann....)
Für Zeichenoperationen nutze ich:
Ich hatte schlussendlich die ganz brutale Variante gewählt, Trunc anstelle von Round verwendet und einfach alles hinter dem Komma abgeschnitten. Im Extremfall wurde halt 4.999 -> 4.

Was ich mal mitbekommen habe, das dieses Problem von der CPU aus kommt.
Viel leicht kennt einer eine Option, wie man dies umschalten kann ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von Mathias »

Da scheint C ausnahmsweise FPC überlegen zu sein, da wird richtig gerundet.

Quelle: https://www.delftstack.com/de/howto/c/r ... tion-in-c/

Code: Alles auswählen

#include <stdio.h>
#include <math.h>
int main () {
  float f0 = 0.499;
  float f1 = 0.500;
  for (int i = 0; i < 8; i++){
    printf ("i: %i  x.499: %i      x.500: %i \n", i,  lround(f0),  lround(f1));
    f0 += 1.0;
    f1 += 1.0;
  }
}
Ausgabe:

Code: Alles auswählen

i: 0  x.499: 0      x.500: 1 
i: 1  x.499: 1      x.500: 2 
i: 2  x.499: 2      x.500: 3 
i: 3  x.499: 3      x.500: 4 
i: 4  x.499: 4      x.500: 5 
i: 5  x.499: 5      x.500: 6 
i: 6  x.499: 6      x.500: 7 
i: 7  x.499: 7      x.500: 8 
x.499 wird schön brav abgerundet und x.500 aufgerundet.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

sstvmaster
Beiträge: 576
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von sstvmaster »

Es gibt: Get/SetRoundMode.

https://www.freepascal.org/docs-html/rt ... dmode.html

Code: Alles auswählen

program Project1;

uses Math;

var
  i: integer;
  x: double;
  rm: TFPURoundingMode;

begin
  rm := GetRoundMode; // safe inital round mode

  SetRoundMode(rmUp); // <-- 
  x := 0.5;
  for i:=0 to 10 do begin
    WriteLn('Input:', x:10: 5, ' round: ', Round(x));
    x:=x+1.0;
  end;


  SetRoundMode(rm); // write back inital round mode
  ReadLn;
end.  
Ergibt:
Input: 0.50000 round: 1
Input: 1.50000 round: 2
Input: 2.50000 round: 3
Input: 3.50000 round: 4
Input: 4.50000 round: 5
Input: 5.50000 round: 6
Input: 6.50000 round: 7
Input: 7.50000 round: 8
Input: 8.50000 round: 9
Input: 9.50000 round: 10
Input: 10.50000 round: 11
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von Mathias »

Es gibt: Get/SetRoundMode.
Dies ist ja noch dümmer als vorher.
Aus 4.001 wird 5.

Einzig SetRoundMode(rmNearest); ist ein wenig besser. Nur wird da auch 4.5 abgerundet, erst bei 4.5001 geht es hinauf.

Ich habe mir SetRoundMode genauer angeguckt, er macht schon etwas mit der FPU.

Code: Alles auswählen

    procedure Set8087CW(cw:word);
      begin
         default8087cw:=cw;
         asm
           fnclex
           fldcw cw
         end;
      end;     
Einziges was mir gerade einfällt, ist folgendes, welches nicht so schön ist.

Code: Alles auswählen

uses
  ctypes;

  function lround(f: cdouble): clong; cdecl; external 'm';
  function lroundf(f: cfloat): clong; cdecl; external 'm';
  ...
  WriteLn(lround(4.5000));
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Joh
Lazarusforum e. V.
Beiträge: 191
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von Joh »

Vor allem wirkt sich SetRoundMode auch auf die Oberfläche aus; die Anordnung der Button / die Schriftgröße etc.
just my two Beer

Benutzeravatar
Ally
Beiträge: 263
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Fliesskommazahlen und Ungenauigkeiten

Beitrag von Ally »

Hallo,

wenn auf eine bestimmte Anzahl von Nachkommastellen gerundet werden soll, hätte ich noch diesen Vorschlag:

Code: Alles auswählen

// Kaufmännisches Runden nach DIN 1333 mit Angabe der Nachkommastellen (benötigt Math)
function RoundEX(AValue: Extended; Digits: Integer): Extended;
var
  M: Integer;
begin
  M := 10 ** Digits;
  if AValue >= 0 then
    Result := Trunc(AValue * M + 0.5) / M
  else
    Result := Trunc(AValue * M - 0.5) / M;
end;

Gruß Ally

Antworten