Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Unterschiedliche Ergebnisse beim Runden (https://www.delphipraxis.net/193551-unterschiedliche-ergebnisse-beim-runden.html)

Ritsch 14. Aug 2017 14:59

Unterschiedliche Ergebnisse beim Runden
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hey Community,

ich stehe vor einem Problem, welches ich im Moment nicht verstehe.

Ich möchte eine Zahl runden mit folgendem Code

Code:
var i: Int64;
begin
[...]
  i:= Round(zahl*multi);
[...]
end;
Der Wert der sich aus der Multiplikation ergibt lautet 7.50000000000728
Das sollte gerundet 8 ergeben.

In i wird allerdings 7 gespeichert. Wenn ich aber den Ausdruck auswerte, erhalte ich 8.

Im Anhang sind nochmal zwei Bilder.



Mache ich etwas falsch?

hoika 14. Aug 2017 15:03

AW: Unterschiedliche Ergebnisse beim Runden
 
Hallo,
traue diesen "überwachten Ausdrücken" einfach nicht ...
Wie oft ich da schon drüber gestolpert bin bei TDateTime.

Ritsch 14. Aug 2017 15:07

AW: Unterschiedliche Ergebnisse beim Runden
 
In einem neuem Projekt ergibt

Code:
var
  i: Int64;
begin
  i:= Round(7.50000000000728);
i = 8.

Das soll mal einer verstehen :?

mkinzler 14. Aug 2017 15:19

AW: Unterschiedliche Ergebnisse beim Runden
 
Es ist auch ein Unterschied zwischen eine Berechnung und einer Konstante.

Welche Typen haben Zahl und Multi?

nahpets 14. Aug 2017 15:25

AW: Unterschiedliche Ergebnisse beim Runden
 
Round(FesteGleitkommazahl) ist was anderes als Round(ZahlEinesTyps * ZahlEinesAnderenTyps).

Von welchem Typ sind zahl und multi?

Vor dem Aufruf von Round werden die Zahlen, sofern sie von unterschiedlichem Typ sind, in einen "einheitlichen" Typ gewandelt, das kann dann schonmal schiefgehen bzw. nicht zum erwarteten Ergebnis führen.

Wenn ich sowas auf die unelegante Art mache, dann sieht das ungefähr so aus:
Delphi-Quellcode:
i := Round((zahl + 0.00) * (multi + 0.00));
Dadurch werden ggfls. Integerwerte erstmal in Gleitkomma umgewandelt, damit bei der Berechnung Nachkommastellen erhalten bleiben.

Das kann so funktionieren, muss aber nicht.

Wenns nicht anders geht dann eher sinngemäß sowas:
Delphi-Quellcode:
var i: Int64;
    dZahl : Double;
    dMulti : Double;
    dGes  : Double;
begin
[...]
  dZahl := zahl;
  dMulti := multi;
  dGes  := dZahl * dMulti;
  i     := Round(dGes);
[...]
end;
Und nein, das ist nicht elegant :-(

mikhal 14. Aug 2017 15:36

AW: Unterschiedliche Ergebnisse beim Runden
 
Schau mal in der Hilfe nach, dort wird der Standard-Modus rmNearest beschrieben und zur besseren Erläuterung ein Link zu einem Blog bei Microsoft geteilt.

Zitat:

The Round function goes to the nearest integer, and if there are two nearest integers then it goes to the even one. 1.5 rounds to 2, 0.5 rounds to 0
Dein 7,5 ist mit 8 korrekt, wenn dein Ergebnis aber 6,5 wäre, dann wäre demnach 6 korrekt - eben die nächste gerade Ganzzahl.

Grüße
Mikhal

Uwe Raabe 14. Aug 2017 15:46

AW: Unterschiedliche Ergebnisse beim Runden
 
Ich verwende in solchen Fällen immer die Routinen von John Herbster: ID: 21909, DecimalRounding (JH1).

Wenn man jetzt ein kleines Testprogramm hätte, das den Fehler reproduziert, dann könnte man auch sehen, ob er damit behoben wird.

mensch72 14. Aug 2017 18:02

AW: Unterschiedliche Ergebnisse beim Runden
 
Ein Teil unseres Hauptgeschäfts ist der Finanzbereich, und speziell da gibt es von KundeZuKunde Unterschiede in den Vorgaben, wie die ".5er" Rundungsregel ausfallen soll.

Wir meiden "double" wie der Teufel das Weihwasser, heißt wir rechnen intern eh fast alles selbst mit einem eigenen 48..64Bit FixComma Typen mit eigenen überladenen Operatoren was(seit Delphi2007) problemlos funktioniert.
- wir bevorzugen und setzen als Defaulteinstellung für uns bei "exakt .5" die GERADZAHLREGEL. Bei ungenauen 0.5 knapp drüber oder knapp drunter runden wir auf oder ab.
- wir bieten eine externe Epsilon Anpassung, um den Bereich des "exakt .5" bei Bedarf selbst passend zu beeinflussen
- wir bieten optional auch eine statische Festlegung der Rundungsrichtung bei "exakt .5", also kann ein Kunde wenn er möchte da immer auf oder abrunden
- unsere Einstellungen gelten immer programmweit und ohne Beachtung und Kenntnis des Berechnungszwecks... kein Kunde kann sagen er möchte alles fürs eignene Haben aufgerundet und alles fürs eigene Soll abgerundet bekommen... auch wenn mindestens ein Konkurrenzprodukt sowas bietet weigere ich mich das auch so zu programmieren... wie man sieht ist "Rundung" also ein sehr komplexes und teils auch emotionales oder gar rechtlich durchaus relevantes Thema

p80286 14. Aug 2017 18:48

AW: Unterschiedliche Ergebnisse beim Runden
 
ich habe mir mal hiermit beholfen:
Delphi-Quellcode:
integer:=trunc(fließkomma+0.5);
Gruß
K-H

Luckie 14. Aug 2017 19:29

AW: Unterschiedliche Ergebnisse beim Runden
 
Also das:
Code:
0.5 rounds to 0
ist ja mathematisch falsch. Wie kommen die auf die Regel zur nächsten geraden Zahl zu runden?

Uwe Raabe 14. Aug 2017 19:35

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Luckie (Beitrag 1378723)
Wie kommen die auf die Regel zur nächsten geraden Zahl zu runden?

Dieses sogenannte Banker's Rounding soll die Gleichverteilung der Ergebnisse gewährleisten. Andernfalls würde das Aufrunden ja tendenziell bevorzugt. Mit dem Banker's Rounding hält man den Summen-Rundungsfehler statistisch in engeren Grenzen.

Thomas Feichtner 14. Aug 2017 19:37

AW: Unterschiedliche Ergebnisse beim Runden
 
Hallo,

für das kaufmännische Runden verwende ich folgende Funktion:

Delphi-Quellcode:
function xRound(e: Extended; d: Integer ): Extended;
var
  nWert1: Extended;
  nTemp1: Currency;
begin
  { Zuerst Zahl multiplizieren, damit diese als Currency arbeiten kann
    damit bei xRound(2.51 * (100 - 74.5) / 100, 4) = 0.6401 auskommt und nicht
    0.64 }
  // Wenn Grenzwerte überschritten werden, wird geschützt gearbeitet
  if (d>4) or (abs(e)>999999) then begin
    try
      nTemp1 := e * IntPower(10, d - 1);
    except
      Result := e;
      exit;
    end;
  end
  else begin
   nTemp1 := e * IntPower(10, d - 1);
  end;

  if nTemp1 < 0.0 then
    nTemp1 := Trunc(nTemp1 * IntPower(10, 1) - 0.5 ) / IntPower(10, 1)
  else
    nTemp1 := Trunc(nTemp1 * IntPower(10, 1) + 0.5 ) / IntPower(10, 1);
  nWert1 := nTemp1 / IntPower(10, d - 1);
 
  Result := nWert1;
end;

jaenicke 14. Aug 2017 19:41

AW: Unterschiedliche Ergebnisse beim Runden
 
Lustig wird es, wenn man Geräte wie einen Fiskaldrucker ansteuert. Da muss man dann nämlich exakt genauso runden wie der es tut.

Luckie 14. Aug 2017 19:56

AW: Unterschiedliche Ergebnisse beim Runden
 
@Uwe: Danke. Aber ich hätte das mathematische korrekte Runden als Standard gewählt.

Benedikt Magnus 14. Aug 2017 20:51

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Luckie (Beitrag 1378727)
@Uwe: Danke. Aber ich hätte das mathematische korrekte Runden als Standard gewählt.

Dieses merkwürdige Runden ist das "mathematisch korrekte" (was sowieso nur eine Definitionssache darstellt), vor allem im statistischen Bereich ist das sehr wichtig, aber auch überall sonst sorgt es dafür, wie Uwe bereits beschrieben haben, dass die Rundungen in größerem Kontext unverzerrt bleiben.
Das kaufmännische Runden, die Juristen nennen es "Bürgerliches Runden", ist lediglich die einfachere Variante, die dann eingesetzt wird, wenn die Verzerrung durch das häufigere Aufrunden irrelevant ist oder in Kauf genommen wird. Sprich vor allem im kaufmännischen und schulischen Bereich.
Ich muss zugeben, dass ich die mathematisch korrekte Variante vor dem Statistikteil meines Studiums auch nicht kannte. Ist aber auch nicht die einzige mathematische Methode, die man jahrelang "salopp" beigebracht bekommt und erst dann richtig, wenn man sie wirklich braucht. :-D

Luckie 14. Aug 2017 21:55

AW: Unterschiedliche Ergebnisse beim Runden
 
Moment. So habe ich es in der Schule gelernt. Ab 0,5 und drüber wird aufgerundet, da runter abgerundet. Und nicht auf die nächst gerade Zahl.

Eventuell sollten wir Begriffe definieren. Mathematisch, wie oben beschrieben. Kaufmännisch und dieses Bänker runden.

Mathematisch, siehe oben, wie in der Schule gelehrt.

Über diese verschiedenen Rundungsverfahren habe ich mir schon immer den Kopf zerbrochen. :roll:

gammatester 14. Aug 2017 22:12

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Luckie (Beitrag 1378732)
Moment. So habe ich es in der Schule gelernt. Ab 0,5 und drüber wird aufgerundet, da runter abgerundet.

Und wie rundest Du -0.5? Wenn ja, warum?

p80286 14. Aug 2017 22:36

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von gammatester (Beitrag 1378734)
Zitat:

Zitat von Luckie (Beitrag 1378732)
Moment. So habe ich es in der Schule gelernt. Ab 0,5 und drüber wird aufgerundet, da runter abgerundet.

Und wie rundest Du -0.5? Wenn ja, warum?

-0.5=0.5*-1 also 1*-1

Gruß
K-H

himitsu 15. Aug 2017 03:36

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Luckie (Beitrag 1378727)
@Uwe: Danke. Aber ich hätte das mathematische korrekte Runden als Standard gewählt.

Das kannst du bei dir ja gern machen.

Delphi-Referenz durchsuchenGet8087CW
Delphi-Referenz durchsuchenSet8087CW
Delphi-Referenz durchsuchenGetRoundMode
Delphi-Referenz durchsuchenSetRoundMode

8086 = CPU (central processing unit)
8087 = FPU (floating point unit)
GPU (graphics processing unit) .... uhhh, Codename "Pascal" für nvidia GeForce 1000er Serie (GeForce GTX 1060, ...)
Southbridge, Northbridge, Soundcard usw.
Damals waren das noch einzelne Chips, aber Heute ist das ja oft nur noch ein Chip.


Bei 7.50000000000728 muß man eben aufpassen, ob es auch in die Variable passt, bevor es gerundet wird und auch nach dem Runden.
Wenn es nur das mathematische Ergebnis ist, aber der Typ das nur als 7.499999998 speichert, dann wird da eventuell anders gerundet.
Also in einem Single sollte der Wert schonmal nicht gespeichert werden, da dort nicht genug signifikante Dezimalstellen existieren.

Ritsch 15. Aug 2017 06:59

AW: Unterschiedliche Ergebnisse beim Runden
 
Danke für eure zahlreichen Antworten.
Habe es jetzt folgendermaßen gelöst.

Anstatt
Code:
var i: Int64;
begin
[...]
  i:= Round(zahl*multi);
[...]
end;
so
Code:
var i: Int64;
    d: double;
begin
  [...]
  d:= zahl * multi;
  i:= Round(d);
end;

Ghostwalker 15. Aug 2017 07:22

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Luckie (Beitrag 1378732)
Moment. So habe ich es in der Schule gelernt. Ab 0,5 und drüber wird aufgerundet, da runter abgerundet. Und nicht auf die nächst gerade Zahl.

Eventuell sollten wir Begriffe definieren. Mathematisch, wie oben beschrieben. Kaufmännisch und dieses Bänker runden.

Mathematisch, siehe oben, wie in der Schule gelehrt.

Über diese verschiedenen Rundungsverfahren habe ich mir schon immer den Kopf zerbrochen. :roll:

[KLUGSCHEISSMODUS ON]
Alle drei sind mathematisch korrekte Rundungsmethoden.

kaufmännische Rundung: Alles incl. 0.5 wird aufgerundet.
technische Rundung: 0.5 und darunter wird abgerundet.

mathematische Rundung (bankers rounding):

.00 bis .49 wird abgerundet
.60 bis .99 wird aufgerundet
.51 bis .59 wird aufgerundet

.50 wird derart gehandelt,das die beizubehaltende Zahl zur nächsten geraden Zahl gerundet wird.
Bsp dafür:

2.25 wird zu 2.2
2.35 wird zu 2.4


Letzteres ist bereits auf Prozessor-Ebene so implementiert (zumindest bei x86) und wird standardmäßig
von den entsprechenden Sprachen incl(Delphi....schon seit Turbo Pascal-Zeiten) so für Rundungen verwendet.

https://de.wikipedia.org/wiki/Rundung
[/KLUGSCHEISSMODUS OFF]

und hier mal meine Routine für alle drei Methoden:

Delphi-Quellcode:
TYPE
   TRoundMethod = (rmKfm,rmTec,rmMat);

function RoundDirect(zahl:extended;dezimalstellen:Byte;methode:TRoundMethod=rmKfm):extended;
var
  hlp,hlp2,di : Extended;

begin
  di := Power(10,dezimalstellen);
  hlp := trunc(zahl*di);
  hlp2 := (zahl*di)-hlp;
  case methode of
     rmKfm : if (hlp2 >= 0.5) then hlp := hlp+1;
     rmTec : if (hlp2 > 0.5) then hlp := hlp+1;
     rmMat: begin
               if (hlp2 > 0.5) then hlp := hlp+1
               else
               begin
                 if (odd(trunc(hlp))) then hlp := hlp +1;
               end;

             end;
  end;
  result := hlp/di;
end;

Luckie 15. Aug 2017 10:35

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

mathematische Rundung (bankers rounding):

.00 bis .49 wird abgerundet
.60 bis .99 wird aufgerundet
.51 bis .59 wird aufgerundet

.50 wird derart gehandelt,das die beizubehaltende Zahl zur nächsten geraden Zahl gerundet wird.
Bsp dafür:

2.25 wird zu 2.2
2.35 wird zu 2.4
Und genau so habe ich es in der Schule im Matheunterricht nicht gelernt. Da wurde mir beigebracht, dass 0,5 immer aufgerundet wird und nicht zur nächsten geraden Ziffer. Also wird in der Mittelstufe im Matheunterricht das technische Runden gelehrt?

samso 15. Aug 2017 11:33

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Luckie (Beitrag 1378762)
Und genau so habe ich es in der Schule im Matheunterricht nicht gelernt. Da wurde mir beigebracht, dass 0,5 immer aufgerundet wird und nicht zur nächsten geraden Ziffer. Also wird in der Mittelstufe im Matheunterricht das technische Runden gelehrt?

Die Vermittlung mehrere Rundungsverfahren würde euch verunsichern. :wink:

Die Wahl des Rundungsverfahrens hängt doch von der Anwendung ab. Wenn der Schlüssel ins Schloss passen soll, ist es günstiger bei der Berechnung abzurunden, damit es am Ende nicht klemmt.

Jasocul 15. Aug 2017 11:34

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Luckie (Beitrag 1378762)
Also wird in der Mittelstufe im Matheunterricht das technische Runden gelehrt?

Das nennt sich"kaufmännisches Runden" oder auch "bürgerliches Runden" und reicht für den Alltag völlig aus. Da es eine sehr einfache Form der Rundung ist und i.d.R. für den Alltag völlig ausreichend ist, wird diese auch in der Schule unterrichtet. Ich meine mal gehört zu haben, dass es dafür sogar eine DIN-Norm gibt. Die Abweichungen im kaufmännischen Bereich sind zu vernachlässigen. Deshalb wird diese Rundung auch bei Rechnungen, Steuererklärungen, ... verwendet.

Die andere Form der Rundung spielt insbesondere bei Statistiken eine Rolle, da dadurch die die Ergebnisse weniger verfälscht werden. Daher wird es auch verzerrungsfreie Rundung genannt. Ich glaube dass es auch bei der Vermessung und Navigation eine Rolle spielt, aber das ist schon so lange her, dass ich mir nicht mehr ganz sicher bin. Der Einsatz ist daher eher im mathematisch-technischen Bereich zu finden.

Luckie 15. Aug 2017 11:36

AW: Unterschiedliche Ergebnisse beim Runden
 
Belassen wir es dabei. Wenn ich es mal brauche, kann ich mich ja noch mal informieren. :roll:

mensch72 15. Aug 2017 12:03

AW: Unterschiedliche Ergebnisse beim Runden
 
..."ist ja mathematisch falsch. Wie kommen die auf die Regel zur nächsten geraden Zahl zu runden?"...
also wir habe das Runden von ".5" per "GeradZahlRegel" schon in der Schule in Mathematik so gelernt und dann überall in Physik, Chemie, E-Technik uws. angewannt.
Bei uns nannte man die ersten 10Jahre die Schule "POS" ala "Polytechnische-Oberschule", und zumindest Mathematik und Naturwissenschaften wurden da garnicht so schlecht und sogar fast politikfrei gelehrt.

Mathematisch und vor allem statistisch dient die "GeradZahlRegel" der Gleichverteilung der Rundungsfehler, was sich problemlos beweisen lässt.
Aber da es nunmal so ist, das es heute teils von Bundesland zu Bundesland und Schulart zu Schulart verschiedene Lehrstandards gibt und die Diskussion darüber müßig ist, haben wir unsere Software zentral einstellbar gemacht, da kann der Chef es sich so festlegen, das es so ist wie er es gelernt hat und/oder es für richtig hält:)

Das Grundsatzproblem der nunmal FPU und letztendlich doch binär basierten Fließkommatypen kommt ja immer noch dazu, und sollte VOR DEM RUNDEN beachtet werden... also erst mal die "gewollte Zahl" REKONSTRUIEREN, dann das Ergebnis wie es so schön heißt auf nötige und sinnvolle Genauigkeit RUNDEN.



Wen all das eigentlich garnicht interessiert, der nehme einfach "integer:=Round(double);" und es wird zu 99% etwas sinvolles heraus kommen.

Amateurprofi 16. Aug 2017 09:09

AW: Unterschiedliche Ergebnisse beim Runden
 
Hallo Richard,
Es ist ja schön, dass du dein Problem gelöst hast, wie in #20 gezeigt, aber es wäre doch noch etwas schöner, wenn auch geklärt worden wäre, was eigentlich das Problem war.
Leider hast du auf die direkte Frage in #4 "Welche Typen haben Zahl und Multi?" nicht geantwortet.
In den Screenshots konnte man sehen, dass Multi den Wert 10 und Zahl den Wert 0.075 hatte, wobei interessant gewesen wäre, wie der Wert 0.075 entstanden war.

In den vielen Themen wurde leider meist an deinem Problem vorbei geredet, denn mit den unterschiedlichen Methoden des Rundens hatte das nichts zu tun.

Das Problem ist, dass Zahlen, die in dezimaler Schreibweise exakt dargestellt werden können, in binärer Schreibweise nicht exakt darstellbar sind.

Ich hab mal geprüft, wie die Werte X=0.075 und 10*X in der FPU aussehen, wenn vorher X unterschiedliche Typen hat.
In der nachstehenden Tabelle seht ihr jeweils den Typ von X, den Wert in der FPU in dezimaler Darstellung mit 20 Nachkommstellen und den Speicherauszug des Wertes in der FPU.

Code:
CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat:
Single   0.07500000298023223880  00 00 00 00 00 9A 99 99 FB 3F
Real48    0.07500000000004547470  00 00 00 9A 99 99 99 99 FB 3F
Double   0.07499999999999999720  00 98 99 99 99 99 99 99 FB 3F
Extended 0.07500000000000000000  9A 99 99 99 99 99 99 99 FB 3F

CPU interne Darstellung von 10 * X=0.075, wobei X den jeweils angegebenen Typ hat:
Single   0.75000002980232238800  00 00 00 00 80 00 00 C0 FE 3F
Real48    0.75000000000045474700  00 00 80 00 00 00 00 C0 FE 3F
Double   0.74999999999999997200  00 FE FF FF FF FF FF BF FE 3F
Extended 0.75000000000000000000  00 00 00 00 00 00 00 C0 FE 3F
Man sieht sehr schön, dass wenn 0.075 in einem Double gespeichert war, in der FPU daraus ein Wert wird, der geringfügig kleiner ist.
Das Gleiche passiert auch bei dem mit 10 multiplizierten Wert, der dann, auf 7 gerundet wird, und zwar unabhängig davon, welche Methode der Rundung verwendet wird.

Die Tabelle wurde mit der nachstehenden Routine erstellt:
Delphi-Quellcode:
PROCEDURE TestRounding;
type TTBA=Array[0..9] of Byte;
PROCEDURE Store(Value:Extended; Typ:String; var S:String);
var I:Integer; T:String;
begin
   Str(Value:0:20,T);
   S:=S+#13#10+Typ+' '+T+' ';
   for I:=0 to 9 do S:=S+' '+IntToHex(TTBA(Value)[I],2);
end;
const
   H1='CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat:';
   H2='CPU interne Darstellung von 10 * X=0.075, wobei X den jeweils angegebenen Typ hat:';
   ZahlS:Single=0.075;
   ZahlR:Real48=0.075;
   ZahlD:Double=0.075;
   ZahlE:Extended=0.075;
var I:Integer; S:String;
begin
   S:=H1;
   Store(ZahlS,'Single ',S);
   Store(ZahlR,'Real48  ',S);
   Store(ZahlD,'Double ',S);
   Store(ZahlE,'Extended',S);
   S:=S+#13#10#13#10+H2;
   Store(10*ZahlS,'Single ',S);
   Store(10*ZahlR,'Real48  ',S);
   Store(10*ZahlD,'Double ',S);
   Store(10*ZahlE,'Extended',S);
   Clipboard.AsText:=S;
end;

Uwe Raabe 16. Aug 2017 09:53

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von Amateurprofi (Beitrag 1378827)
In den Screenshots konnte man sehen, dass Multi den Wert 10 und Zahl den Wert 0.075 hatte, wobei interessant gewesen wäre, wie der Wert 0.075 entstanden war.

Das ist nicht ganz richtig: In dem ScreenShot aus #1 hat Multi den Wert 100. Andernfalls wäre ja auch nicht 7,5 das erwartete Ergebnis.

Ansonsten hast du natürlich recht mit der internen Darstellung.

Das folgende Beispielprogramm demonstriert das (zumindest unter Win32):

Delphi-Quellcode:
program Project262;

{$APPTYPE CONSOLE}

var
  MultiS: Single;
  WertS: Single;
  MultiD: Double;
  WertD: Double;
begin
  MultiS := 100;
  MultiD := 100;
  WertS := 0.075;
  WertD := 0.075;
  Writeln('Single: ', Round(MultiS * WertS));
  Writeln('Double: ', Round(MultiD * WertD));
  Readln;
end.
Es lässt sich aber auch zeigen, daß die Verwendung der von mir vorgeschlagenen Unit das Problem löst:

Delphi-Quellcode:
program Project263;

{$APPTYPE CONSOLE}

uses
  DecimalRounding_JH1;

var
  MultiS: Single;
  WertS: Single;
  MultiD: Double;
  WertD: Double;
begin
  MultiS := 100;
  MultiD := 100;
  WertS := 0.075;
  WertD := 0.075;
  Writeln('Single: ', Round(MultiS * WertS));
  Writeln('Double: ', Round(MultiD * WertD));
  Writeln('Single JH: ', DecimalRoundSgl(MultiS * WertS, 0));
  Writeln('Double JH: ', DecimalRoundDbl(MultiD * WertD, 0));
  Readln;
end.

Amateurprofi 16. Aug 2017 11:16

AW: Unterschiedliche Ergebnisse beim Runden
 
@Uwe,
Oh, das ist mir jetzt aber peinlich.
Na klar war Multi=100 gesetzt.
Ich hab noch mal die Tabelle auf Basis Multi=100 erstellt.

CPU interne Darstellung von X=0.075, wobei X den jeweils angegebenen Typ hat:
Single 0.07500000298023223880 00 00 00 00 00 9A 99 99 FB 3F
Real48 0.07500000000004547470 00 00 00 9A 99 99 99 99 FB 3F
Double 0.07499999999999999720 00 98 99 99 99 99 99 99 FB 3F
Extended 0.07500000000000000000 9A 99 99 99 99 99 99 99 FB 3F

CPU interne Darstellung von 100 * X=0.075, wobei X den jeweils angegebenen Typ hat:
Single 7.50000029802322388000 00 00 00 00 A0 00 00 F0 01 40
Real48 7.50000000000454747000 00 00 A0 00 00 00 00 F0 01 40
Double 7.49999999999999972000 80 FD FF FF FF FF FF EF 01 40
Extended 7.50000000000000000000 01 00 00 00 00 00 00 F0 01 40

freimatz 21. Aug 2017 14:51

AW: Unterschiedliche Ergebnisse beim Runden
 
Zitat:

Zitat von mensch72 (Beitrag 1378719)
Ein Teil unseres Hauptgeschäfts ist der Finanzbereich, ...
Wir meiden "double" wie der Teufel das Weihwasser, ...

Das möchte ich nochmals unterstreichen. Bei Währungen verwendet "man" NIE, NIE (In Worten NIE) Fließkomma.

Luckie 21. Aug 2017 15:22

AW: Unterschiedliche Ergebnisse beim Runden
 
Dafür gibt es ja auch den Datentyp Currency.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:36 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