Autor Thema: Fehler in Fact  (Gelesen 7093 mal)

0 Mitglieder und 1 Gast betrachten dieses Thema.

alexdrik

  • Gast
Fehler in Fact
« am: 15. März 2011, 20:56:18 »
Hallo,

der Baustein FACT liefert für 13 einen falschen Wert zurück.
Richtig wäre 6227020800, das ist aber mit DINT nicht darstellbar, deswegen wird 1932053504 zurückgeliefert.
Außerdem liefert FACT für negative Werte nicht -1 zurück, sondern die Fakultät des positiven Wertes.

Wäre es nicht effektiver, die Werte vorzuberechnen und mittels CASE auszuwählen?

CASE x OF
  0: fact :=                                      1;
  1: fact :=                                      1;
  2: fact :=                                      2;
  3: fact :=                                      6;
  4: fact :=                                    24;
  5: fact :=                                  120;
  6: fact :=                                  720;
  7: fact :=                                5040;
  8: fact :=                              40320;
  9: fact :=                            362880;
10: fact :=                         3628800;
11: fact :=                       39916800;
12: fact :=                     479001600;
(* für 64Bit-Werte
13: fact :=                   6227020800;
14: fact :=                 87178291200;
15: fact :=             1307674368000;
16: fact :=           20922789888000;
17: fact :=         355687428096000;
18: fact :=       6402373705728000;
19: fact :=   121645100408832000;
20: fact := 2432902008176640000;
*)
ELSE
    fact_ad :=                                 -1;
END_CASE



Offline hugo

  • Global Moderator
  • *****
  • Beiträge: 2 150
    • Profil anzeigen
Re:Fehler in Fact
« Antwort #1 am: 15. März 2011, 21:54:00 »
den ferhler mit 13 werden wir prüfen,
allerdings -1 für negative werte ist schlichtweg falsch, fakultät für negative werte ist nicht definiert und deshalb ist auch die antwort -1 falsch.
das wäre geleichbedeutend als für 34/0 eione -1 zurückzuliefern.

wie bei jeder mathematischen funktion muss der programmierer den wertebereich einhalten.

alexdrik

  • Gast
Re:Fehler in Fact
« Antwort #2 am: 16. März 2011, 20:01:42 »

Hmmm, wenn man die Werte in ein Array packt, dann hat man das Problem mit den negativen Werten nicht.
Vorberechnen kann man di dann auch:

Deklaration:
   werte : ARRAY[0..12] OF DINT :=1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600;

Implementation:
     IF X > 12 THEN
        Fact := -1;
     ELSE
        Fact := werte
  • ;

     END_IF

Offline hugo

  • Global Moderator
  • *****
  • Beiträge: 2 150
    • Profil anzeigen
Re:Fehler in Fact
« Antwort #3 am: 18. März 2011, 12:16:38 »
die fact von 13 haben wir ausgeschlossen, den sie übersteigt den wertebereich von dint.
die lösung mittels array sieht zwar super aus, ist aber bedeutend langsamer weil bei jedem asufruf das ganze array auf den stack kopiert werden muss
in release 332 wird der fehler korrigiert

alexdrik

  • Gast
Re:Fehler in Fact
« Antwort #4 am: 24. März 2011, 20:48:04 »
Hallo,

wenn man das Array in die Struktur CONSTANTS_MATH aufnimmt, dann wird es einmal global angelegt und nicht jedesmal in den Stack kopiert werden.

Offline hugo

  • Global Moderator
  • *****
  • Beiträge: 2 150
    • Profil anzeigen
Re:Fehler in Fact
« Antwort #5 am: 25. März 2011, 06:49:54 »
richtig das werde ich mir nochmal ansehen

Offline hugo

  • Global Moderator
  • *****
  • Beiträge: 2 150
    • Profil anzeigen
Re:Fehler in Fact
« Antwort #6 am: 26. März 2011, 07:05:41 »
fact mittels array ist ca doppelt so schnell, habe ich entsprechend realisiert