"rundungs" Fehler ?

Zugriff, Engines, Konvertierung. Von ADS über DBF bis zu SQL.

Moderator: Moderatoren

Antworten
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

"rundungs" Fehler ?

Beitrag von AUGE_OHR »

hi,

erstmal ein frohes neues Jahr 2008 !

so nun zu meinem Problem :

Code: Alles auswählen

ARTNR  Artikel                         VkGesamt   Bestand  Lager  Diff

*1128E Gelber Fisch 400-600g KLAR      150.0000   7.2000   7.2000   0.0000
*1315  Hühnerfüsse                      40.0000   1.0000   7.0000  -6.0000
*1360  Enten gegr.Thai 550-600g BKK    568.0000   0.0000  35.0000 -35.0000
*4381E Suppe, MAGGI Sauer & Scharf     126.0200   8.0000   8.0000   0.0000
*6104E Cashew-Nüsse W320er             558.9500   0.7200   0.7200   0.0000
*6405E Sesam, weiß                      64.7000   6.8000   6.8000   0.0000
der Code dazu sieht so aus

Code: Alles auswählen

PROCEDURE MAIN()

SET DECIMALS TO 4
SET FIXED ON

   CLS

SET ALTER TO ARTDIFF.TXT
SET ALTER ON

   USE ARTIKEL
   SET INDEX TO ARTNR,AALPHA,CODE
   ?
   ? "ARTNR  Artikel                         VkGesamt   Bestand  Lager  Diff"
   ?
   GO TOP
   DO WHILE !EOF()
*      IF ( ROUND(BESTAND,2) <> ROUND(Lagerein-Lageraus,2) )
      IF ( BESTAND <> (Lagerein-Lageraus) )
         ? "*"+ARTNR  +" "+;
               ARTIKEL+" "+;
           STR(VKGESAMT,9,4)+" "+;
           STR(BESTAND ,8,4)+" "+;
           STR(Lagerein-Lageraus,8,4)+" "+;
           STR(BESTAND-(Lagerein-Lageraus),8,4)
      ENDIF
      SKIP
   ENDDO

SET ALTER TO
SET ALTER OFF

RETURN

/*
 FELDER

{ "BESTAND"     ,"N" ,         8,         2 } ,;
{ "VKGESAMT"    ,"N" ,         8,         2 } ,;
{ "LAGEREIN"    ,"N" ,        10,         2 } ,;
{ "LAGERAUS"    ,"N" ,        10,         2 } ,;

*/
klar funktioniert es wenn ich ein ROUND() benutzte, aber trotzdem würde
ich gerne wissen warum bei 4 (von 3345 ) Positionen trotz 0.0000 nicht
richtig funktioniert ?

gruss by OHR
Jimmy
Benutzeravatar
Bertram Hansen
Foren-Moderator
Foren-Moderator
Beiträge: 1015
Registriert: Di, 27. Sep 2005 8:55
Wohnort: 51379 Leverkusen
Hat sich bedankt: 28 Mal
Danksagung erhalten: 20 Mal
Kontaktdaten:

Beitrag von Bertram Hansen »

Hallo Jimmy,

früher (unter Clipper) hatte ich mit Round() auch Probleme. Ich nutze jetzt folgende Funktion.

Code: Alles auswählen

FUNCTION R_OUND( lan_wert1, lan_wert2)
IF lan_wert1 < 0
   RETURN( ROUND( ABS(lan_wert1) + (1/10^10), lan_wert2) * -1)
ENDIF   
RETURN( ROUND( lan_wert1 + (1/10^10), lan_wert2))
:wave:
Gruß Bertram
http://www.tobax.de
Mitglied der XUG Cologne
Mitglied der XUG Osnabrück
Beisitzer des Deutschsprachige Xbase-Entwickler e.V.

Solange Kakaobohnen an Bäumen wachsen ist Schokolade Obst!
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

hi,
Bertram Hansen hat geschrieben: früher (unter Clipper) hatte ich mit Round() auch Probleme. Ich nutze jetzt folgende Funktion.
Mit ROUND() geht es ja. Es geht um die Zeile

Code: Alles auswählen

IF ( BESTAND <> (Lagerein-Lageraus) ) 
Wo er 4 Treffer mit 0.0000 hat ... wieso ?
Wenn ich multiplizieren/dividieren würde könnte ich es ja noch verstehen,
aber ich subtrahiere ja nur sodas die Stellen nach dem "Komma" doch
alle "glatt" sein sollten ???

gruss by OHR
Jimmy
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Beitrag von Rolf Ramacher »

Hi Jimmy,

versuch es doch mal so:

IF ( ROUND(BESTAND,2) <> ROUND((Lagerein-Lageraus),2) )

außerdem solltest du bei der Anzeige das so machen:

STR((Lagerein-Lageraus,8,4))+" "+;
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

hi,
Rolf Ramacher hat geschrieben: versuch es doch mal so:
IF ( ROUND(BESTAND,2) <> ROUND((Lagerein-Lageraus),2) )
Jaja mit ROUND() geht es (siehe Source) aber warum geht es ohne NICHT ???

Ich subtrahiere doch nur und habe 4stellen hinter dem Komma 0.000 ???
Die FELDer haben ja auch nur 2stellen hintem Komma und sind 0.00.

gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

SET DECIMALS TO 15

Beitrag von AUGE_OHR »

hi,

SET DECIMALS TO 15

Code: Alles auswählen

? BESTAND, Lagerein, Lageraus, (Lagerein-Lageraus)  // FELDer
? "*"+ARTNR  +" "+;
...

ARTNR  Artikel                         VkGesamt   Bestand  Lager  Diff

    7,200000000000000     157,200000000000000     150,000000000000000
    7,199999999999989
*1128E Gelber Fisch 400-600g KLAR      150.0000   7.2000   7.2000   0.0000

    8,000000000000000     134,020000000000000     126,020000000000000
    8,000000000000015
*4381E Suppe, MAGGI Sauer & Scharf     126.0200   8.0000   8.0000   0.0000

    0,720000000000000     559,670000000000000     558,950000000000100
    0,719999999999914
*6104E Cashew-Nüsse W320er             558.9500   0.7200   0.7200   0.0000

    6,800000000000000      71,500000000000000      64,700000000000000
    6,799999999999998
*6405E Sesam, weiß                      64.7000   6.8000   6.8000 0.0000
nun "sehe" ich zwar was, aber das "warum" beim subtrahieren ist mir in
den 4 Fällen nicht klar. (... da ja die anderen 3341 funktionieren)

... und wie kann ein FELD "N",10,2 einen Wert 558,950000000000100 haben ?

gruss by OHR
Jimmy
Benutzeravatar
Markus Walter
Programmier-Gott
Programmier-Gott
Beiträge: 1018
Registriert: Di, 24. Jan 2006 10:22
Wohnort: Saarland

Re: SET DECIMALS TO 15

Beitrag von Markus Walter »

AUGE_OHR hat geschrieben:hi,

SET DECIMALS TO 15

Code: Alles auswählen

? BESTAND, Lagerein, Lageraus, (Lagerein-Lageraus)  // FELDer
? "*"+ARTNR  +" "+;
...

ARTNR  Artikel                         VkGesamt   Bestand  Lager  Diff

    7,200000000000000     157,200000000000000     150,000000000000000
    7,199999999999989
*1128E Gelber Fisch 400-600g KLAR      150.0000   7.2000   7.2000   0.0000

    8,000000000000000     134,020000000000000     126,020000000000000
    8,000000000000015
*4381E Suppe, MAGGI Sauer & Scharf     126.0200   8.0000   8.0000   0.0000

    0,720000000000000     559,670000000000000     558,950000000000100
    0,719999999999914
*6104E Cashew-Nüsse W320er             558.9500   0.7200   0.7200   0.0000

    6,800000000000000      71,500000000000000      64,700000000000000
    6,799999999999998
*6405E Sesam, weiß                      64.7000   6.8000   6.8000 0.0000
nun "sehe" ich zwar was, aber das "warum" beim subtrahieren ist mir in
den 4 Fällen nicht klar. (... da ja die anderen 3341 funktionieren)

... und wie kann ein FELD "N",10,2 einen Wert 558,950000000000100 haben ?

gruss by OHR
Jimmy
Hi Jimmy,

das Feld hat nicht diesen Wert, sondern die interne Darstellung der Zahl zur Laufzeit. Xbase kennt als einzigen "numerischen" Datentyp den "float", also keine Ganzzahlen, sondern Gleitkommazahlen (Clipper übrigens meines Wissens auch). Und damit wird die Darstellung einer Dezimalzahl zum Glücksfall (vor allem bei JEDER Rechenoperation, auch bei Plus oder Minus).
Aus diesem Grund sind Vergleiche von Zahlen IMMER problematisch. Du könntest beim Prüfen auf Null empty() benutzen, dass hat meines Wissens einen "Unschärfebereich".
Ansonsten mit round() oder abs() arbeiten oder in Strings wandeln, alles andere ist Roulette...
Gruß
Markus

Mitglied der XUG Saarland-Pfalz
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: SET DECIMALS TO 15

Beitrag von AUGE_OHR »

hi,
Markus Walter hat geschrieben:
AUGE_OHR hat geschrieben:hi,
558,950000000000100
[/code]
... und wie kann ein FELD "N",10,2 einen Wert 558,950000000000100 haben ?
das Feld hat nicht diesen Wert, sondern die interne Darstellung der Zahl zur Laufzeit. Xbase kennt als einzigen "numerischen" Datentyp den "float", also keine Ganzzahlen, sondern Gleitkommazahlen (Clipper übrigens meines Wissens auch).
Das hat mich auf die Idee gebraucht den Code mal durch Cl*pper zu
jagen und : 558,950000000000000
Markus Walter hat geschrieben: Und damit wird die Darstellung einer Dezimalzahl zum Glücksfall (vor allem bei JEDER Rechenoperation, auch bei Plus oder Minus).
Aus diesem Grund sind Vergleiche von Zahlen IMMER problematisch. Du könntest beim Prüfen auf Null empty() benutzen, dass hat meines Wissens einen "Unschärfebereich".
Ansonsten mit round() oder abs() arbeiten oder in Strings wandeln, alles andere ist Roulette...
scheinbar reagiert Cl*pper geringfügig anders, wirft aber auch die 4 Sätze
raus sodas man auch beim subtrahieren doch ROUND() einsetzten muss.

gruss by OHR
Jimmy


gruss by OHR
Jimmy
Antworten