Greyhound verrechnet sich

  • Hallo,


    ich wundere mich gerade warum meine Kollegen seit Wochen nur noch volle Stunden arbeiten. Unsere Zeiterfassung zeigt nämlich nur noch einstellige Arbeitszeiten.


    Ich habe mir dann die entsprechende Regel zur Brust genommen und wundere mich darüber das Round(549.9999984)/100 = 5 ergibt. Der komplette Befehl lautet:

    Code
    1. Item.UserFields.ItemsByName['f_durationHours'].AsFloat := Round(((Item.EndDate - Item.StartDate) * 24) * 100) / 100;


    Da stimmt doch was nicht, oder?


    Lieben Gruß

  • Hallo,


    die ganze Rundung ist an der Stelle unfug... ;)


    Mal zum technischen Hintergrund:


    Round(549.9999984) ergibt einen ganzzahlungen Wert von 550. Teilt man eine ganze Zahl, bekommt man keinen Float mehr. Wenn das gewünscht ist, muss das Ergebnis von Round explizit auf Double umgewandelt werden.


    Also so:


    Code
    1. Double(Round(549.9999984)) / 5

    Die Multiplikation mit 100 und das Dividieren durch 100 erhöht dabei aber weder die Präzision, noch entfernt es die durch die Fließkomma ungenauigkeit entstandenen überflüssigen Nachkommastellen. Fließkommazahlen sind immer unpräzisie bei den hinteren Nachkommastellen, gerade bei der Ausgabe fällt das auf. Umgehen kann man das bei der Ausgabe, indem man diese zum Beispiel mit Format ausgibt (Doku dazu fehlt leider noch, Fremdoku). Bei der Verwendung in Benutzerdefinierten Feldern ist diese Möglichkeit aber etwas eingeschränkt. Eventuell kann man den Wert hier mit Format (Sprachabhängig) als String ausgeben: Format('%.2f', Value). Beim "herausholen" kann man mit [url='http://greyhound-software.com/docs/script/functions/SysUtils.StrToFloatDef']StrToFloatDef[/url] arbeiten.


    Das benutzerdefinierte Feld ist dabei vom Typ "String".

  • Hey Oliver,


    aber ich habe doch vom Meister abgeguckt -> Differenz zwischen zwei Datumsangaben berechnen ?(


    Unfug hin oder her - Fakt ist aber das es bisher funktioniert hat und seit einiger Zeit nicht mehr. Das hat mich gewundert. Ob es vorher richtig oder falsch war das richtige Ergebnisse raus kamen kann ich nicht beurteilen.


    Das mit Double und Format schaue ich mir mal an. Das ganze in ein Benutzerdefiniertes Stringfeld zu schreiben würde es aber umständlicher machen mit diesem Wert Berechnungen durchzuführen.


    Melde mich... :-)

  • Hallo,


    das * 100 und / 100 macht doch Sinn. Aus 123,45678 wird so ja 12345,678. Nach dem Runden haben wir dann 12346 und nach dem teilen 123,46 (wenn die Ungenauigkeit von Float nicht wieder ein paar Neunen oder Nullen mit einer Eins am Ende dran hängt). Die Scriptsprachen Version wurde in der Zwischenzeit geupdated, ggf. war dies einer der Punkte, welcher unter "diverse Korrekturen" lief. ;)

  • Aha! ;)


    Habe die Zeile nun wie folgt umgeschrieben und nun funktioniert es wieder.


    Code
    1. // Termindauer in Stunden berechen
    2. try
    3. if Item.UserFields.Exists('f_durationHours') then
    4. Item.UserFields.ItemsByName['f_durationHours'].AsFloat := Double(Round(((Item.EndDate - Item.StartDate) * 24) * 100)) / 100;
    5. except
    6. end;