Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Ungenauigkeit beim Speichern?


cerebrum - Do 13.02.03 16:42
Titel: Ungenauigkeit beim Speichern?
Hallo!
Wenn der Benutzer eine Zahl im Zehnersystem eingibt dann wird diese ja zur Abspeicherung ins Binärsystem umgewandelt. Bei der Rückkonvertierung ins Zehnersystem kommt es dann zu einer gewissen Ungenauigkeit. Wie kann ich diese ausgleichen?


Delete - Do 13.02.03 16:48

Was machst du genau? Ich habe da noch keine Ungenauigkeit festgestellt. Und was für einen Datentyp hast du: Integer, Single, Extended, ...?


Christian S. - Do 13.02.03 16:49

Bei der Konvertierung ins Binärsystem entsteht keinerlei Ungenauigkeit. Beide System sind gleichwertige Basen für die Zahlendarstellung. Die Ungenauigkeit kommt daher, dass im Rechner nicht die gesamten reellen Zahlen dargestellt werden können, sondern nur eine Teilmenge. Dabei kannst Du Dir die Menge der reellen Zahlen, die vom Rechner dargestellt werden können, als die Menge der reelllen Zahlen nur "mit Löchern" und als beschränktes Intervall vorstellen. Integerzahlen sind ein beschränktes Intervall der natürlichen Zahlen, aber ohne "Löcher".
Die Ungenauigkeit kann nicht ausgeglichen werden.


maximus - Do 13.02.03 17:22

ergo: zB 0,2 kannst du nicht genau festlegen, da bräuchtest du einen typ der 2^oo (unendlich) bits hat. Dh. jeh mehr bits desto genauer...extended hat glaub ich 80 bits.


DaRkFiRe - Do 13.02.03 19:38

maximus hat folgendes geschrieben:
ergo: zB 0,2 kannst du nicht genau festlegen, da bräuchtest du einen typ der 2^oo (unendlich) bits hat. Dh. jeh mehr bits desto genauer...extended hat glaub ich 80 bits.


...was eigentlich reichen sollte.

Bei der Umwandlung einer irrationalen Zahl (z.B. PI, oder 1/3) in eine Binärzahl kommt es zu einer gewissen Ungenauigkeit, welche allerdings schon bei der Verarbeitung im Rechner auftritt, bzw. natürliche Gründe hat. Diese kann man nicht ausgleichen. Und 80 Bit sollten für eine Zahlendarstellung (vorerst) eigentlich reichen, oder!?

Für Integer gibt es keine Umwandlungsungenauigkeit - sie werden 100%ig umgewandelt - hin UND zurück!


Delete - Do 13.02.03 19:59

:arrow: Deswegen nie Fließkommazahlen mit "=" vergleichen. :idea:


tommie-lie - Do 13.02.03 20:39

:?:
Warum nicht?
0,2 = 0,2 gilt doch immer. Ob 0,2 nun intern jedes mal 0,199999999999999999999999 ist, spielt doch keine Rolle, an sich sind die Zahlen doch gleich, odeR? Genauso wie (1/3) = (1/3). Oder habe ich irgendwas ganz grundlegendes nicht mitbekommen?


Delete - Do 13.02.03 20:42

Dann vergleich mal:

Quelltext
1:
1/3 mit 0,3333333...                    


Christian S. - Do 13.02.03 21:00

Oder pack mal einen Button und 2 Labels auf eine Form und benutze diesen Code:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Button1Click(Sender: TObject);
VAR f,g : Real;
begin
  f:=1.999;
  g:=sqrt(f)*100000;
  g:=g*sqrt(f);
  f:=f*100000;
  label1.caption:=FloatToStr(f);
  label2.caption:=FloatToStr(g);
  if f = g then ShowMessage('Gleich!');
end;

In den Labels sind die beiden Zahlen gleich (und sollten es ja auch sein), aber Delphi ist da anderer Meinung!

MfG,
Peter


tommie-lie - Fr 14.02.03 14:39

@Luckie: Das wäre auch ohne beschränkte Genauigkeit nicht gleich, da man nicht unendlich viele 3en hinter dem Komma setzen kann, weder auf dem Papier, noch sonstwo...

@Peter: Das schon eher. Da scheinen es tatsächlich rundungsfehler zu sein, die beim Wurzelziehen entstehen.

Aber: (1/3) = (1/3) geht immer noch. Es liegt also nicht direkt an Fließkommazahlen, sondern eher an der Verarbeitung: Wenn man vorher komplex mit rechnet, dann kann's in die Hose gehen.

Und wie kriegt man es hin, wenn man sowas wie in Peter's code wirklich machen will? Also wenn man zwei Rechnungen anstellt, bei denen mathematisch gesehen das gleiche rauskommt, aber der Prozessor zu ungenau ist?


Christian S. - Fr 14.02.03 16:08

So:

Quelltext
1:
2:
if a = b then //so nicht
if Abs(a-b)<0.00001 then //sondern so

Was Du auf die rechte Seite von < schreibst, hängt davon ab, wie genau Du das Ganze gerne hättest.

MfG,
Peter