Autor |
Beitrag |
digiveit
Hält's aus hier
Beiträge: 10
Windows XP Professional
Delphi 6 Enterprise
|
Verfasst: Mi 22.10.08 10:39
Hallo zusammen,
ich gebe eine Kommazahl in ein Edit-Feld ein. Diese soll dann in eine Variable vom Typ Single umgewandelt werden und mit libnodave an eine S7 geschickt werden.
Jetzt habe ich das Problem, dass nach der Zuweisung an die Single-Variable mir Nachkommastellen erzeugt werden, die ich nicht haben möchte.
Hat jemand eine Ahnung warum das so ist?
Hier mein Quellcode:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| var s1: WideString; e1: Double; sgl1: Single;
begin
s1 := edtGewicht.Text; e1 := StrToFloat(s1); sgl1 := e1; NoDave.WriteFloat(12, e1); end; |
Hab es auch schon mit RoundTo usw. probiert, aber ohne Erfolg.
Was mache ich da falsch?
Vielen Dank schon mal für Eure Hilfe!
MfG
Veit
Moderiert von matze: Code- durch Delphi-Tags ersetzt
|
|
hazard999
      
Beiträge: 162
Win XP SP2
VS 2010 Ultimate, CC.Net, Unity, Pex, Moles, DevExpress eXpress App
|
Verfasst: Mi 22.10.08 10:47
Auszug aus WP:
[zitat]
Schon einfache Dezimalzahlen, z. B. 0,1, können nicht mehr exakt als binäre Gleitkommazahlen dargestellt werden, da viele im Dezimalsystem abbrechende Kommazahlen im Binärsystem nicht abbrechende, periodische Zahlen sind; von diesen werden nur die ersten p Ziffern gespeichert, wodurch Ungenauigkeit entsteht. Dezimal 0,1 ist binär 0,0001100110011… In einem binären Gleitkommasystem ist also 10 · 0,1 < 1, da die 0,1 abgerundet wird und nicht den exakten Wert approximiert.
[/zitat]
Das passiert wenn du einen Datentyp grösserer Genauigkeit in einen mit kleiner Genauigkeit umwandelst.
_________________ MOV EAX, Result;MOV BYTE PTR [EAX], $B9;MOV ECX, M.Data;MOV DWORD PTR [EAX+$1], ECX;MOV BYTE PTR [EAX+$5], $5A;MOV BYTE PTR [EAX+$6], $51;MOV BYTE PTR [EAX+$7], $52;MOV BYTE PTR [EAX+$8], $B9;MOV ECX, M.Code;MOV DWORD PTR [EAX+$9], ECX
|
|
Gausi
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mi 22.10.08 10:49
Das liegt an der internen Darstellung der Zahl im Binärsystem. Der Wert 1,369 kann im Dualsystem nicht genau dargestellt werden (oder nur mit sehr viel mehr Stellen), so dass es dann zu Ungenauigkeiten kommt.
Wirklich beheben kann man das nicht, evtl. ist der Datentyp Currency was für dich. Oder klappt vielleicht die direkte Zuweisung MySingleVar := StrToFloat(sMyString); besser?
_________________ We are, we were and will not be.
|
|
hazard999
      
Beiträge: 162
Win XP SP2
VS 2010 Ultimate, CC.Net, Unity, Pex, Moles, DevExpress eXpress App
|
Verfasst: Mi 22.10.08 10:49
Einmal konvertieren ist besser:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var s1: string; sing: single; begin s1 := Edit1.Text; sing := StrToFloatDef(s1, 0); end; |
_________________ MOV EAX, Result;MOV BYTE PTR [EAX], $B9;MOV ECX, M.Data;MOV DWORD PTR [EAX+$1], ECX;MOV BYTE PTR [EAX+$5], $5A;MOV BYTE PTR [EAX+$6], $51;MOV BYTE PTR [EAX+$7], $52;MOV BYTE PTR [EAX+$8], $B9;MOV ECX, M.Code;MOV DWORD PTR [EAX+$9], ECX
|
|
Timosch
      
Beiträge: 1314
Debian Squeeze, Win 7 Prof.
D7 Pers
|
Verfasst: Mi 22.10.08 11:11
Warum überhaupt Single? Warum nicht Extended?
_________________ If liberty means anything at all, it means the right to tell people what they do not want to hear. - George Orwell
|
|
digiveit 
Hält's aus hier
Beiträge: 10
Windows XP Professional
Delphi 6 Enterprise
|
Verfasst: Mi 22.10.08 11:34
Timosch hat folgendes geschrieben : | Warum überhaupt Single? Warum nicht Extended? |
Weil ich mit libnodave die Daten an eine SPS S7-Steuerung schicken möchte und dort der Übergabeparameter ein Single ist:
Delphi-Quelltext 1:
| NoDave.WriteFloat(12, sgl1); |
Ich möchte halt in der SPS genau 1,369 drin stehen haben und nicht 1,368999958.
Muss doch irgendwie machbar sein, oder nicht?!?
MfG
Veit
|
|
mkinzler
      
Beiträge: 4106
Erhaltene Danke: 13
Delphi 2010 Pro; Delphi.Prism 2011 pro
|
Verfasst: Mi 22.10.08 12:24
Dann runde den Wert auf die gewüsnchte Anzhal von Stellen
_________________ Markus Kinzler.
|
|
digiveit 
Hält's aus hier
Beiträge: 10
Windows XP Professional
Delphi 6 Enterprise
|
Verfasst: Mi 22.10.08 15:43
mkinzler hat folgendes geschrieben : | Dann runde den Wert auf die gewüsnchte Anzhal von Stellen |
Hab ich auch schon probiert.
Geht aber nicht
Delphi-Quelltext 1:
| sgl2 := RoundTo(sgl1, -3); |
liefert mir in sgl2 wieder den Wert mit den vielen Kommastellen.
Noch andere Vorschläge?
MfG
Veit
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Mi 22.10.08 15:46
bei drei Nachkommastellen nimm doch currency!
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Mi 22.10.08 16:27
Lass man, eigentlich ist das das Gleiche (1,369 vs. 1,368999958), Du bemängelst einen Fehler von 0,000003%, das ist lächerlich. Es ist nunmal so, wie oben schon erwähnt, das sich die Zahl 1,369 *NICHT* exakt in einem Single-Datentyp darstellen lässt. Punkt.
Grundsätzlich: Bei Floating Point-Datentypen muss man die letzten 2-3 Stellen ignorieren.
Bei Deinem Problem würde ich (nun nicht gerade bei dem einfachen Beispiel) mit Double oder Extended rechnen und dann den Wert vor der Übergabe in einen Single umrechnen. Mit Single würde ich nur sehr einfache Rechnungen durchführen.
Wenn Du z.B. einen Stab der Länge 100cm hast, ist der garantierte nie genau 100cm lang. In diesem Fall wäre er 100,000003 cm lang. Na nun.
_________________ Na denn, dann. Bis dann, denn.
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Do 23.10.08 14:10
Aber wenn man currency nimmt, treten KEINE Rundungsfehler auf!!
Weil Currency-Daten nicht als Gleitkommazahlen gespeichert werden, sondern als integer.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Do 23.10.08 14:18
Boldar hat folgendes geschrieben : | Aber wenn man currency nimmt, treten KEINE Rundungsfehler auf!! |
Und wenn man sie in Single konvertiert?  Die tritt doch spätestens bei der Übergabe an die SPS auf.
Currency ist ein sehr schöner Datentyp, wenn man nur addiert bzw. subtrahiert, weil man sich dann nicht mit den Schutzstellen herum ärgern muss. Als allgemeiner Datentyp in wissentschaftlich-mathematischen Anwendungen eignet er sich jedoch aufgrund der beschränkten Genauigkeit nicht.
_________________ Na denn, dann. Bis dann, denn.
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Do 23.10.08 14:36
currency-->nach string
string---> nach single
konvertieren, dann treten keine Rundungsfehler auf.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Do 23.10.08 14:44
_________________ Na denn, dann. Bis dann, denn.
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Do 23.10.08 18:10
ok, garnicht...
Du hast recht.
Denkfehler^^
|
|
|