![]() |
Vergleich von Real-Werten ---> klappt nicht
Hallo,
nachfolgend der problematische Code:
Delphi-Quellcode:
mehrmals nachgerechnet : Rv ist genau 634
Const
E96 : array[1..98] of Real = (0, 1.0, 1.02, 1.05, 1.07, 1.1, 1.13, 1.15, 1.18, 1.21, 1.24, 1.27, 1.30, 1.33, 1.37, 1.40, 1.43, 1.47, 1.50, 1.54, 1.58, 1.62, 1.65, 1.69, 1.74, 1.78, 1.82, 1.87, 1.91, 1.96, 2.0, 2.05, 2.1, 2.15, 2.21, 2.26, 2.32, 2.37, 2.43, 2.49, 2.55, 2.61, 2.67, 2.74, 2.80, 2.87, 2.94, 3.01, 3.09, 3.16, 3.24, 3.32, 3.40, 3.48, 3.57, 3.65, 3.74, 3.83, 3.92, 4.02, 4.12, 4.22, 4.32, 4.42, 4.53, 4.64, 4.75, 4.87, 4.99, 5.11, 5.23, 5.36, 5.49, 5.62, 5.76, 5.90, 6.04, 6.19, 6.34, 6.49, 6.65, 6.81, 6.98, 7.15, 7.32, 7.50, 7.68, 7.87, 8.06, 8.25, 8.45, 8.66, 8.87, 9.09, 9.31, 9.53, 9.76, 10); ...... implementation var Rv : Real; // Rv ist 634 for i := 2 to 98 do if Rv = (E96[i-1] * multi) then // <<<<< wird nicht erkannt !!!!!!!!!! begin lb96Min.Caption := FloatToStr(E96[i-1] * multi) + ' Ohm'; lb96Max.Caption := ''; break; end; // <<<<< hier bekomme ich 634 und 649 zurück for i := 1 to 98 do if (Rv > E96[i-1] * multi) and (Rv < E96[i] * multi) then begin lb96Min.Caption := FloatToStr(E96[i-1] * multi) + ' Ohm'; lb96Max.Caption := FloatToStr(E96[i] * multi) + ' Ohm'; break; end; multi ist ein Multiplikator, Typ Integer, hier 100 warum wird der direkte Vergleich nicht erkannt ? :gruebel: |
Re: Vergleich von Real-Werten ---> klappt nicht
Das nennt man Rundungsfehler, welchen diese Fließkommatypen unterliegen.
Diese Typen können keine beliebigen Zahlen darstellen, sondern nur einen "kleinen" Teil der reellen Zahlen. Darum darf/kann man auch nicht genau auf = prüfen. |
Re: Vergleich von Real-Werten ---> klappt nicht
Dann wird sich 6.34 nicht 100%ig als Real darstellen lassen. Du solltest beim vergleich eine Bandbreite zulassen
|
Re: Vergleich von Real-Werten ---> klappt nicht
Delphi-Quellcode:
Kann nicht funktionieren, da beide intern nicht gleich aussehen, auch wenn du den Real nach Int castest. Als Workaround spontan das hier:
Int(Rv) = (E96[i-1] * multi)
Delphi-Quellcode:
wobei eps in diesem Falle eine Konstante ist, die die Genauigkeit angiebt, bspw.
If Abs(RV - (E96[i-1] * multi)) < eps then
Delphi-Quellcode:
Wobei es vermutlich auch noch andere Ansätze gibt...
const
eps = 0.001; //<> 1E-3 |
Re: Vergleich von Real-Werten ---> klappt nicht
Zitat:
Delphi-Quellcode:
versucht; hier müsste es dann eigentlich funktionieren !?
if Trunc(Rv) = Trunc(E96[i-1] * multi) then ...
|
Re: Vergleich von Real-Werten ---> klappt nicht
Zitat:
mit
Delphi-Quellcode:
funktionierts. Danke
If Abs(RV - (E96[i-1] * multi)) < eps then ...
|
Re: Vergleich von Real-Werten ---> klappt nicht
Eventuell trägt das:
![]() |
Re: Vergleich von Real-Werten ---> klappt nicht
Zitat:
|
Re: Vergleich von Real-Werten ---> klappt nicht
Zitat:
Sei nicht so bescheiden :P |
Re: Vergleich von Real-Werten ---> klappt nicht
Zitat:
|
Re: Vergleich von Real-Werten ---> klappt nicht
nach dem man die Theorie verstanden hat, :-D
kann man es sich auch leichter machen und auf vorhandene Funktionen zugreifen wie z.B.:
Delphi-Quellcode:
alex
uses Math;
function SameValue(..) function IsZero(..) function CompareValue(..) ... Edit:
Delphi-Quellcode:
@Medium, #12: so besser?
function SameValue(const A, B: Single; Epsilon: Single = 0): Boolean; overload;
function SameValue(const A, B: Double; Epsilon: Double = 0): Boolean; overload; function SameValue(const A, B: Extended; Epsilon: Extended = 0): Boolean; overload; function IsZero(const A: Single; Epsilon: Single = 0): Boolean; overload; function IsZero(const A: Double; Epsilon: Double = 0): Boolean; overload; function IsZero(const A: Extended; Epsilon: Extended = 0): Boolean; overload; function CompareValue(const A, B: Integer): TValueRelationship; overload; function CompareValue(const A, B: Int64): TValueRelationship; overload; function CompareValue(const A, B: Single; Epsilon: Single = 0): TValueRelationship; overload; function CompareValue(const A, B: Double; Epsilon: Double = 0): TValueRelationship; overload; function CompareValue(const A, B: Extended; Epsilon: Extended = 0): TValueRelationship; overload; |
Re: Vergleich von Real-Werten ---> klappt nicht
Wobei diese Funktionen durchaus mit Vorsicht zu genießen sind, wenn mit den Werten zuvor sehr viel herumgerechnet wird. Wenn es meinetwegen um die Nte (groooßes N) Iteration einer konvergierenden Reihe geht, und das Ergbnis mit dem erwarteten Grenzwert werglichen werden soll, kann es sein dass das in diesen Funktionen verwendete Epsilon (IMHO ist es das sog. Maschinen-Epsilon) zu klein wird.
Der Vergleich hinkt, da eine Reihe ja per Definition schon nur eine Näherungsfunktion ist, das ganze trifft aber generell zu. Je mehr Operationen ich verwendet habe um zu einem Wert zu kommen, desto heftiger haben sich dabei diese Darstellungfehler aufsummiert, -potenziert, -wasauchimmer-iert. Ich meine aber auch, dass von denen überladene Versionen existieren, bei denen man das Epsilon selbst übergeben kann. Im Grunde sehen die intern auch nicht viel anders aus als das händische abs(wert-vergleichswert)<epsilon, ist im Code nur hübscher leserlich. |
Re: Vergleich von Real-Werten ---> klappt nicht
Hallo zusammen!
Wenn es doch IMMER nur um max. 2 Nachkomma-Stellen geht, kann man doch das Ganze einfach mit 100 multiplizieren. Die Konstanten wären dann also z.B. 102 , 576 oder 805 - und die Ungenauigkeiten sind weg! So rechne ich immer, wenn ich mit Geld-Beträgen zu tun habe - also in Cent und nicht in Euro! Hoffe, das macht es einfacher!? Marcibaer |
Re: Vergleich von Real-Werten ---> klappt nicht
Zitat:
bei den Konstanten gebe ich Dir recht, diese könnten dann Integer-Werte werden. Beim Ergebnis "Rv" nützt das allerdings nicht viel, wenn die Ungenauigkeit erst an vierter, fünfter (oder weiß wo ..) Stelle nach dem Komma auftritt: 102 ist eben nicht gleich 102,0000000012 wie Daniel schon geschrieben hat, nützt da auch das Casten nach Integer nichts. |
Re: Vergleich von Real-Werten ---> klappt nicht
Für Geldbeträge nimmt man Currency, denn dieses rechnet auf 4-Nachkommastellen genau
und ist intern ein skalierter Int64. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz