Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Merkwürdigkeit mit frac und trunc


Daniel L. - Do 17.06.10 17:50
Titel: Merkwürdigkeit mit frac und trunc
Hallo,

wie kann denn das sein?



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure test;
var  e1, e2 : extended;
begin
  e1 := 54.1;
  e2 :=  (frac (e1)) * 60;
  str (e2, s);
  showmessage (s);                        // 600000000000000E+0000  (wie erwartet)    
  showmessage (Inttostr (trunc (e2)));    // 5         (schock!)     
end;

Gruss: Daniel (verwirrt)


Gausi - Do 17.06.10 17:58

Bei dem Späßchen würde ich wieder auf die üblichen und nicht vermeidbaren Ungenauigkeiten bei der internen Fließkommadarstellung tippen. Der Wert von e2 ist halt nicht genau 6, sondern nur so ungefähr, und in diesem Fall wohl ganz knapp darunter. ;-)


Daniel L. - Do 17.06.10 18:09

aber wie sollen denn da Ungenauigkeiten entsehen?
frac (54.1) ist genau 0,1, und das * 60 ist genau 6,
wie können denn da Rundungsungenauigkeiten entstehen?


Gausi - Do 17.06.10 18:13

So, wie man im Dezimalsystem 1/3 nicht exakt darstellen kann (0.33333...) kann man im Binärsystem 1/10 nicht exakt darstellen. Daher kommen dann Ungenauigkeiten zustande, die sich in solchen Dingen bemerkbar machen.


Delete - Do 17.06.10 19:54

Siehe hier: http://www.michael-puff.de/Artikel/Fliesskomma.shtml


jfheins - Fr 18.06.10 00:33

Eine kleine Bitte:

Sobald du mit Gleitkommazahlen zu tun hast streichst du das Wort "genau" aus deinem Wortschatz und ersetzt es durch das Wort "ungefähr"
Ergebnis:

user profile iconDaniel L. hat folgendes geschrieben Zum zitierten Posting springen:
aber wie sollen denn da Ungenauigkeiten entstehen?
frac (54.1) ist ungefähr 0,1 und das * 60 ist ungefähr 6


Hidden - Fr 18.06.10 01:48

Hi :)

Also nimmt eine Gleitkommazahl bei Zuweisung einer dezimalen Kommazahl immer genau den Wert an, der in der Form a(2^-1)+b(2^-2)+..=a/2+b/4+c/8+.. den geringsten Fehlerbetrag aufweist? :lupe:

Dann wäre es unter bestimmten Bedingungen(wie hier) ja durchaus günstig, sich zu überlegen, wie man eine Rechnung umformulieren kann, sodass man eine obere oder untere Schranke für den zu berechnenden Ausdruck erhält.

Interessant wären auch (Assembler-)Funktionen, die umsetzen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
CeilMultiplication(a, b: Extended): Extended;
// returns r \in R >= a*b | r <= s \ForAll s \in R >= a*b
// guaranteed >= a*b multiplication approx.
FloorMultiplication(a, b: Extended): Extended;
// returns r \in R <= a*b | r >= s \ForAll s \in R <= a*b
// guaranteed <= a*b multiplication approx.


lg,