Diskussion zum Thema : "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

  • Dieser Diskussionsthread ist als eine Art 'Gesprächsplattform' zum Sammelthread "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis" gedacht.

    Dadurch lassen sich nun :

    • unterschiedliche Betrachtungsweisen diskutieren
    • Codebeispiele zur Untermauerung des jeweiligen Standpunktes anfügen (daher ist die Shoutbox auch kein adäquater Ersatz)
    • Fragen und allgemeine Kommentare einstellen
    • Hintergründe vertiefen / beschreiben

    Solche Beiträge im Sammelthread selbst zu posten, wäre der Übersichtlichkeit dort auf Dauer eher abträglich.

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    Einmal editiert, zuletzt von Musashi (14. Februar 2019 um 09:03)

  • Zum Beitrag von Bitnugger :

    Sammelthread "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

    Kurzinfo : Subtrahieren von Fließkommazahlen - Ändern der Reihenfolge liefert unterschiedliche Ergebnisse !

    Kommentar von alpines (aus der Shoutbox) :

    "Dazu sei gesagt, dass es nicht die Schuld von AutoIt ist, sondern eher von der C++ STL bzw darauf worauf der Interpreter basiert. C# liefert das selbe "falsche" Ergebnis, es ist aber einfach ein gewöhnlicher Rundungsfehler bei Kommazahlrechnungen."

    Zum Thema "Rundungsfehler" beim Rechnen mit Fließkommazahlen gibt es z.B. im engl. Forum einige Threads. Obwohl es sich hier nicht um einen Fehler im eigentlichen Sinne handelt, so kann das Verhalten für mathematisch weniger versierte User (damit meine ich ausdrücklich nicht Bitnugger ) trotzdem "unerwartet" sein. Ich bin daher der Meinung, dass dieser Beitrag schon in den Sammelthread passt. Eine genauere Beschreibung des Hintergrundes wäre aber sicher sinnvoll ;).

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • --> von Musashi : Eine genauere Beschreibung des Hintergrundes wäre aber sicher sinnvoll ;)

    Die findet man z.B. hier: https://py-tutorial-de.readthedocs.io/de/latest/floatingpoint.html

    Danke - ich hatte gestern Nacht keine Lust mehr nach einem geeigneten Link zu suchen:sleeping:.

    Für Interessierte z.B. auch lesenswert : https://www.mikrocontroller.net/articles/Gleitkommazahlen

    Da AutoIt gerne als Einsteigersprache verwendet wird, dürften vielen Usern die Hintergründe der 'Fließkomma-Arithmetik' nicht bekannt sein ! Von daher läßt sich das Verhalten zwar nicht als Fehler, aber dennoch als 'unerwartet' bezeichnen.

    Gruß Musashi

    P.S. Bitnugger : Könntest Du den py-Link bitte in deinen Beitrag im Sammelthread einfügen ?

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Wer gerne Round benutzt und häufiger ins Hexadezimalsystem vorstößt hat sich sicher schon über Hex(Int(Round($a, 0)), 2) geärgert (also dass man DREI Funktionen braucht um aus 125.5 ein 7E zu machen). Lustigerweise gibt Round($a, 0) ein Double, während Round($a) ein Int32 ausspuckt. Will man also Hex(Round($a)) hat man keine Probleme, solange man die Null weglässt (die ich intuitiv immer erstmal hinmache)

    Code
    Local $a = 125.5
    ConsoleWrite(VarGetType(Round($a)) & @CRLF)
    ConsoleWrite(VarGetType(Round($a, 0)) & @CRLF)
    ConsoleWrite(Hex(Round($a), 2) & @CRLF)
    ConsoleWrite(Hex(Round($a, 0), 2) & @CRLF)

    lg

    M

  • Das hier ist ja der Diskussionsthread.

    Bitnugger zu deiner Gleitkommazahl Konvertierung kann ich nur sagen, dass das kein AutoIt internes Problem sondern ein Problem der Rechnerarithmetik ist.

    Diesem wirst du in jeder Programmiersprache begegnen. Wirf dazu mal einen Blick auf IEEE-754 Converter.

    Offenbar speichert AutoIt die Zahlen als Double und aufgrund dessen bekommst du diese Werte welche nicht exakt 0 sind.

    Allerdings möchte ich hier anmerken, dass man aus diesem Grund (das ist ein beliebter Anfängerfehler) absolut niemals auf Gleichheit prüfen darf, bei Gleitkommazahlen. Es ist stets eine Prüfung um +-epsilon durchzuführen.

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Bitnugger zu deiner Gleitkommazahl Konvertierung kann ich nur sagen, dass das kein AutoIt internes Problem sondern ein Problem der Rechnerarithmetik ist. Diesem wirst du in jeder Programmiersprache begegnen. Wirf dazu mal einen Blick auf IEEE-754 Converter. Offenbar speichert AutoIt die Zahlen als Double und aufgrund dessen bekommst du diese Werte welche nicht exakt 0 sind.

    Hi Xorianator !

    Darauf wird in dem von Bitnugger verlinkten Tutorial auch bereits ausführlich eingegangen :

    https://py-tutorial-de.readthedocs.io/de/latest/floatingpoint.html

    Auszug aus dem py-tutorial :

    14.1. Darstellungsfehler ...

    Der Begriff Darstellungsfehler verweist auf den Umstand das manche (die meisten sogar) Dezimalbrüche nicht exakt als Binärbrüche (Basis 2) dargestellt werden können. Dies ist der Hauptgrund warum Python (oder Perl, C, C++, Java, Fortran, und viele andere) oft nicht das erwartete Ergebnis anzeigen. Warum ist das so? 1/10 ist nicht exakt als Binärbruch darstellbar. Fast alle heutigen Rechner (November 2000) benutzen die IEEE-754 Fließkommaarithmetik und wie fast alle Plattformen, bildet Python floats als IEEE-754 “double precision” ab. IEEE-754 doubles sind auf 53 Bits genau, so dass sich der Computer bemüht, 0.1 mit einem Bruch der Form J/2**N bestmöglich anzunähern, wobei J eine 53 Bit breite Ganzzahl ist.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Wer gerne Round benutzt und häufiger ins Hexadezimalsystem vorstößt hat sich sicher schon über Hex(Int(Round($a, 0)), 2) geärgert (also dass man DREI Funktionen braucht um aus 125.5 ein 7E zu machen).

    Dafür würde ich dann aber Ceiling verwenden...

    ConsoleWrite(Hex(Ceiling($a), 2) & @CRLF)


    Das solltest du aber besser hier schreiben: Sammelthread "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

  • Ceiling, Floor oder Int sind manchmal nicht die beste Wahl, vorallem wenn man Gleitkommarechnungen hat und "runden" möchte (und nicht ab- oder aufrunden).

    Der eigentlich interessante Teil ist das mit Int32 und Double als Returnwert der selben Funktion, je nachdem ob man mit- oder ohne Parameter auf 0 Kommastellen rundet, obwohl man eigentlich in beiden Fällen Int32 ODER Double erwarten würde (als jemand der auch andere Sprachen nutzt erwartet man in beiden Fällen Double)

  • Wer gerne Round benutzt und häufiger ins Hexadezimalsystem vorstößt hat sich sicher schon über Hex(Int(Round($a, 0)), 2) geärgert (also dass man DREI Funktionen braucht um aus 125.5 ein 7E zu machen).

    UND :

    Der eigentlich interessante Teil ist das mit Int32 und Double als Returnwert der selben Funktion, je nachdem ob man mit- oder ohne Parameter auf 0 Kommastellen rundet, obwohl man eigentlich in beiden Fällen Int32 ODER Double erwarten würde (als jemand der auch andere Sprachen nutzt erwartet man in beiden Fällen Double)

    Hi Mars

    Ich sehe es so wie Bitnugger : Das wäre ein passendes Thema für den Sammelthread !

    Einfach einen Beitrag (mit Kurzinfo zu Beginn) erstellen. Wenn Du Zeit und Lust hast ggf. noch ein Codebeispiel beifügen, welches die Besonderheit veranschaulicht.

    Das Einpflegen in die Übersicht mache ich dann.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Hi,

    die eigentliche Frage lautet ja, wieso AutoIt (genau wie die meisten anderen sog. Programmiersprachen auch) nicht in der Lage ist, eine NATIVE Funktion zur Verfügung zu stellen, um "automatisch" ein "richtiges" Ergebnis für eine Fließkommaberechnung bereitzustellen.

    Jeder Vollidiot ist in der Lage, auf seinem Smartphone und/oder dem/einem Windows/Linux "Einfachsttaschenrechner" beliebige Berechnungen mit "richtigem" Ergebnis durchzuführen, ohne dabei auch nur annähernd eine Ahnung von IEEE-754 Fließkommaarithmetik zu haben! Was wiederum die Frage aufwirft, wieso man dieses halbgare Konstrukt benutzt/benutzen muss?!

    *Anm. des Posters* KEINE(R) der o.g. "Einfachstaschenrechner" rechnet mit IEEE-754 Fließkommaarithmetik ;)


    Aber die Anwender einer "Programmiersprache" haben gefälligst selbst dafür zu sorgen bzw. irgendwelche "fremden" Bibliotheken aka UDF´s, bspw. BigNUm.UDF, zu entwickeln bzw. zu benutzen?!

    Ich kenne keinen Programmierer, der nicht mindestens einmal in die Fleisskommaarithmetik-"Falle" getappt ist! Diverse Mond/Weltraummissionen lassen grüßen, und es kann mir niemand erzählen, bei der NASA/ESA sitzen Leute, die vom Thema "keine Ahnung" haben!

    Und das Beispiel

    ConsoleWrite('! 78.08 - 11.07 - 67.01 = ' & 78.08 - 11.07 - 67.01 & @CRLF)

    ist imho einfach nur das Ergebnis eines armselig programmierten Parsers! DER sollte in der Lage sein, selbstständig "richtig" zu Runden, bzw. zu "rechnen".

    Btw. DAS wäre mal ein (AutoIt-) Entwicklungsschritt!

    Per Direktive der Programmiersprache das ganze IEEE-754-Thema auszutreiben und intern auf eine "richtige", aka Festkommaarithmetik mit in der Direktive vorgegebenen Genauigkeit, umzuschalten.

    Denn dann wäre es vollkommen unerheblich, ob ich mein Ergebnis auf 2 oder 200 Nachkommastellen "genau" haben wollte!

  • Hi Mars

    Anregung zu Deinem Beitrag #11 im Sammelthread :

    In Deinem Codebeispiel schreibst Du :

    ConsoleWrite(Hex(5) & ' <> ' & Hex(5.0) & @CRLF) ; Beispiel für eine Funktion die je nach Eingabetyp anderes tut

    Ich habe mal ein alternatives Beispiel gemacht, wo der Bezug zu Round() und Hex() offensichtlicher wird und den Text entsprechend angepasst.

    (neuer Text :)

    Die Funktion Round() gibt, je nachdem ob der optionale Parameter decimalplaces(= Anzahl der Nachkommastellen) gesetzt wird, einen unterschiedlichen Datentyp zurück. Dabei ist es unerheblich, ob man mit decimalplaces auf 0, -1, -2 usw. Nachkommastellen rundet (was ja logischerweise ganzzahlige Werte ergeben muss). Die reine Verwendung des Parameters reicht bereits aus, damit Round() den Datentyp Double liefert (sonst Int32).

    In Kombination mit anderen Funktionen - z.B. Hex() - kann das zu Missverständnissen führen, da sich die Ausgabe je nach Datentyp (Int32, Double) unterscheidet (siehe Codebeispiel).

    Code
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    ConsoleWrite('+ Die Verwendung des optionalen Parameters "decimalplaces" führt zur Rückgabe unterschiedlicher Datentypen : ' & @CRLF)
    ConsoleWrite('! Datentyp ohne "decimalplaces" -> Round(0.5)    = ' & VarGetType(Round(0.5)) & @CRLF)
    ConsoleWrite('! Datentyp mit "decimalplaces"  -> Round(0.5, 0) = ' & VarGetType(Round(0.5, 0)) & @CRLF)
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    ConsoleWrite('+ Beispiel mit der Funktion Hex(), wo der Datentyp den Rückgabewert beeinflusst : ' & @CRLF)
    ConsoleWrite('! Hex mit Round(0.5)    = ' & Hex((Round(0.5))) & @CRLF)
    ConsoleWrite('! Hex mit Round(0.5, 0) = ' & Hex((Round(0.5, 0))) & ' (Anm.: Hex-Repräsentation einer Gleitkommazahl)'& @CRLF)
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)

    Falls Dir diese Variante besser gefallen sollte, kannst Du Deinen Beitrag ja entsprechend anpassen.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Hey, du bist der Boss :D

    Jetzt habe ich schon 2 Verbesserungsvorschläge für meinen Beitrag bekommen 8)

    Dann nehme ich jetzt den Text von Bitnugger, das Codebeispiel von Dir mit der Zahl 5.5 :P

  • Hey, du bist der Boss :D

    Jetzt habe ich schon 2 Verbesserungsvorschläge für meinen Beitrag bekommen 8)

    Dann nehme ich jetzt den Text von Bitnugger, das Codebeispiel von Dir mit der Zahl 5.5 :P

    Hi Mars

    Wenn Du im Codebeispiel die Zahl 5,5 (statt 0.5) verwendest, dann sollte sie besser in alle Texte und Funktionsaufrufe der ConsoleWrites eingetragen werden. Zur Zeit hast Du mal 0.5 im Text und 5.5 in der Funktion - vice versa :P

    Korrekt wäre :

    Code
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    ConsoleWrite('+ Die Verwendung des optionalen Parameters "decimalplaces" führt zur Rückgabe unterschiedlicher Datentypen : ' & @CRLF)
    ConsoleWrite('! Datentyp ohne "decimalplaces" -> Round(5.5)    = ' & VarGetType(Round(5.5)) & @CRLF)
    ConsoleWrite('! Datentyp mit "decimalplaces"  -> Round(5.5, 0) = ' & VarGetType(Round(5.5, 0)) & @CRLF)
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    ConsoleWrite('+ Beispiel mit der Funktion Hex(), wo der Datentyp den Rückgabewert beeinflusst : ' & @CRLF)
    ConsoleWrite('! Hex mit Round(5.5)    = ' & Hex((Round(5.5))) & @CRLF)
    ConsoleWrite('! Hex mit Round(5.5, 0) = ' & Hex((Round(5.5, 0))) & ' (Anm.: Hex-Repräsentation einer Gleitkommazahl)'& @CRLF)
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    Einmal editiert, zuletzt von Musashi (15. Februar 2019 um 08:16)

  • Im Thread Eingebettete GUIs suchte der User u.a. nach einem Fehler bei der GUI-Darstellung.

    Antwort von Bitnugger :

    Du hast aber auch bei GUICreate die Parameter width und height mit left und top vertauscht... deshalb werden die GUIs an falscher Position erstellt, außerhalb des sichtbaren Bereichs !

    Kommentar von BugFix :

    MIt dem Fehler bist du nicht allein - und du wirst ihn auch in 10 Jahren das eine oder andere Mal wiederholen. Denn er ist sehr tückisch in der AutoIt-Syntax "vorhergesehen". Bei Erstellung der GUI wird zuerst width, height und dann left, top angegeben, bei GUI-Ctrl entgegengesetzt erst left, top und dann width, height. Darüber zu stolpern ist also gar nicht so selten ;)

    aus der Hilfe :

    GUICreate ( "title" [, width [, height [, left = -1 [, top = -1 [, style = -1 [, exStyle = -1 [, parent = 0]]]]]]] )

    aber :

    GUICtrlCreateLabel ( "text", left, top [, width [, height [, style = -1 [, exStyle = -1]]]] )  

    GUICtrlCreateButton ( "text", left, top [, width [, height [, style = -1 [, exStyle = -1]]]] )  

    GUICtrlCreateInput ( "text", left, top [, width [, height [, style = -1 [, exStyle = -1]]]] ) GUICtrlCreateEdit ( "text", left, top [, width [, height [, style = -1 [, exStyle = -1]]]] )

    usw.

    Bei GUICtrl... sind left und top Pflichtangaben, width und height hingegen [optional] - daher stehen sie wohl auch am Beginn der Parameter. Bei GUICreate sind alle Angaben [optional].

    Meine Frage :

    Das ist zwar kein Fehler von AutoIt, wohl aber ein potenzieller 'Stolperstein'. Wäre dies also ein Punkt, den ich in den Sammelthread unter Inkonsistenz eintragen sollte ?

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Schau dir mal GUISetState und GUICtrlSetState an.

    Hmm, irgendwie sehe ich den Bezug zur unterschiedlichen Parameterreihenfolge von GUICreate und den GUICrtlCreate's nicht :/.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • State und Bezeichner (GUI/Control) sind vertauscht. Ist zwar nicht left/top width/height aber genau das gleiche Problem.

    Ok, jetzt weiß ich was Du meinst - ich war wohl noch etwas betrübt über das frühzeitige Ableben Deiner Knopfzelle ;).

    Der Kern meiner Frage bleibt aber : "Gehören solche kleinen Fallen in den Sammelthread ?"

    Natürlich nur die Gängigsten, also die, über die insbesondere Einsteiger gerne stolpern - sonst platzt der Thread aus allen Nähten. Auch würde ich nicht für jedes Vorkommen einen eigenen Beitrag einstellen, sondern das Ganze unter einem Punkt z.B. 'Inkonsistenzen bei Funktionsparametern' zusammenfassen.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."