AtNotes Übersicht Willkommen Gast. Bitte einloggen oder registrieren.
30.10.20 - 04:50:54
Übersicht Hilfe Regeln Glossar Suche Einloggen Registrieren
News:
Schnellsuche:
+  Das Notes Forum
|-+  HCL Notes / Domino 11+
| |-+  ND11: Entwicklung (Moderatoren: eknori, fritandr, koehlerbv, Tode)
| | |-+  Kaufmännisches Runden, Lotus Script und Ratlosigkeit
« vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: Kaufmännisches Runden, Lotus Script und Ratlosigkeit  (Gelesen 616 mal)
Riccardo Virzi
Frischling
*
Offline Offline

Beiträge: 18



« am: 14.08.20 - 18:36:02 »

Ich möchte eine Zahl kaufmännisch Runden und schaffe das nicht unter allen Umständen in Lotus Script korrekt zu programmieren.

Dafür gibt es ja den Befehl Round. Da ist aber, meiner Meinung nach, in der Doku schon ein Fehler drin, den ich reproduzieren kann:
' Round to one decimal place.
Print Round(4.23, 1)                    ' Prints 4.2      -> RICHTIG
Print Round(4.35, 1)                    ' Prints 4.4      -> RICHTIG
Print Round(4.45, 1)                    ' Prints 4.4      ->  Huh FALSCH, sollte eigentlich 4.5 ausgeben, oder?

Damit kann ich den Round Befehl nicht nutzen. Deswegen mache ich bisher in meiner Programmierung folgendes:
1. verschiebe das Komma nach rechts durch Multiplikation mit 100 (für 2 Nachkommastellen, bei 3 Stellen muß 1000 genommen werden, usw.)
2. danach addiere ich 0,5
3. mit dem Skript Befehl Fix entferne ich die Nachkommastellen
4. verschiebe das Komma nach links durch Division mit 100 (für 2 Nachkommastellen, bei 3 Stellen muß 1000 genommen werden, usw.)

Code:
Fix( ( Wert * 100 ) + 0,5 ) / 100

Das funktioniert schon seit fast 2 Jahrzehnten gut. Bis ich eine Beschwerde Anfang der Woche bekommen habe, daß die MWSt. nicht korrekt berechnet wird.
Zu meinem Erstaunen, mußte ich festellen, daß tatsächlich der Cent Betrag nicht ok ist. Ich kann aber keinen Fehler in meiner Logik entdecken, bzw. bin ratlos wie ich den Fehler lösen soll.
Zum besseren Verständniss warum ich ratlos bin, habe ich 4 Beispiele und den Code zum Test angehängt.

Ein Beispiel mit dem Wert 64,3652 (gerundet 64,37):
   64,3652 * 100   = 6436,52
   6436,52 + 0,5   = 6437,02
   Fix( 6437,02 )   = 6437
   6437 / 100        = 64,37

Alles ok soweit. Dann schaun wir mal was mit 64,365 passiert (gerundet 64,37):
   64,365 * 100    = 6436,5
   6436,5 + 0,5    = 6437
   Fix( 6437 )       = 6436           Huh
   6436 / 100       = 64,36

Ups, nicht mehr so gut. Dasselbe mache ich mal mit dem Wert 64,2652 (gerundet 64,27):
   64,2652 * 100   = 6426,52
   6426,52 + 0,5   = 6427,02
   Fix( 6427,02 )   = 6427
   6427 / 100        = 64,27

Alles ok soweit. Dann schaun wir mal was mit 64,265 passiert (gerundet 64,27):
   64,265 * 100    = 6426,5
   6426,5 + 0,5    = 6427
   Fix( 6427 )       = 6427
   6427 / 100       = 64,27

Auch alles gut! Ob mir jemand das Verhalten erklären kann, weiß ich nicht. Aber vielleicht gibt es andere Möglichkeiten die ich noch nicht bedacht habe.

Wer bis hier gekommen ist  Grin und sich dann meine Beispiele ansieht, der könnte sich folgendes fragen: warum nimmt der eigentlich Fix und nicht CInt um eine Zahl mit Nachkommastellen in eine Zahl ohne Nachkommastellen umzuwandeln?
Ganz einfach: das hatte ich tatsächlich damals programmiert, bis ein Fall aufgetreten ist, in dem der Befehl CInt/CLng ähnlich falsch reagiert hat. Die Zahl finde ich leider nicht mehr und frage deswegen bei Euch, ob das Problem beim Runden bekannt ist und jemand Ideen hat.

Hier ist ein Skript Code Beispiel, mit dem das Verhalten geprüft werden kann:
   Dim WertOriginal As Double
   Dim WertGerundet As Double
   
   WertOriginal = 64.3652
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,37 = RICHTIG

   WertOriginal = 64.365
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,36 = FALSCH
   
   WertOriginal = 64.2652
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,27 = RICHTIG

   WertOriginal = 64.265
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,27 = RICHTIG
   

Nochmal ein Beispiel mit den Befehlen Round, CDbl, CInt und DLng:
   Dim WertOriginal As Double
   Dim WertGerundet As Double
   
   WertOriginal = 64.3652
   WertGerundet = Round( WertOriginal, 2 )               ' WertGerundet = 64,37 = RICHTIG
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,37 = RICHTIG
   WertGerundet = CDbl( ( ( WertOriginal * 100.0 ) + 0.5 ) / 100 )   ' WertGerundet = 64,3702 = RICHTIG aber nicht gerundet
   WertGerundet = CInt( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,37 = RICHTIG
   WertGerundet = CLng( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,37 = RICHTIG
   
   WertOriginal = 64.365
   WertGerundet = Round( WertOriginal, 2 )               ' WertGerundet = 64,36 = FALSCH
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,36 = FALSCH
   WertGerundet = CDbl( ( ( WertOriginal * 100.0 ) + 0.5 ) / 100 )   ' WertGerundet = 64,37 = RICHTIG
   WertGerundet = CInt( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,37 = RICHTIG
   WertGerundet = CLng( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,37 = RICHTIG
   
   WertOriginal = 64.2652
   WertGerundet = Round( WertOriginal, 2 )               ' WertGerundet = 64,27 = RICHTIG
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,27 = RICHTIG
   WertGerundet = CDbl( ( ( WertOriginal * 100.0 ) + 0.5 ) / 100 )   ' WertGerundet = 64,2702 = RICHTIG aber nicht gerundet
   WertGerundet = CInt( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,27 = RICHTIG
   WertGerundet = CLng( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,27 = RICHTIG

   WertOriginal = 64.265
   WertGerundet = Round( WertOriginal, 2 )               ' WertGerundet = 64,26 = FALSCH
   WertGerundet = Fix( ( WertOriginal * 100.0 ) + 0.5 ) / 100      ' WertGerundet = 64,27 = RICHTIG
   WertGerundet = CDbl( ( ( WertOriginal * 100.0 ) + 0.5 ) / 100 )   ' WertGerundet = 64,27 = RICHTIG
   WertGerundet = CInt( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,27 = RICHTIG
   WertGerundet = CLng( ( ( WertOriginal * 100.0 ) + 0.5 ) ) / 100   ' WertGerundet = 64,27 = RICHTIG
Gespeichert
CarstenH
Senior Mitglied
****
Offline Offline

Geschlecht: Männlich
Beiträge: 311



« Antworten #1 am: 14.08.20 - 22:09:41 »

Zuerst einmal - die Round() Funktion im Lotus Script führt das mathematische und nicht das kaufmännische Runden durch, das ist in der Doku auch so beschrieben: If the first non-significant digit is 5, and all subsequent digits are 0, the last significant digit is rounded to the nearest even digit.

Für die kaufmännische Version und auch die Probleme mit den Double-Variablen gab es hier vor längerer Zeit schon einmal einen Thread hier der auch eine Lösung in Form einer doppelten Konvertierung nannte, vielleicht löst das ja dein Problem:

https://atnotes.de/index.php/topic,53931.msg350309.html#msg350309

HTH
Carsten
Gespeichert
ronka
Senior Mitglied
****
Offline Offline

Beiträge: 293


Was macht der hier denn, muß der überall sein ?


WWW
« Antworten #2 am: 16.08.20 - 12:58:15 »

,365 = ,364999999999999

Und damit geht es schief.
« Letzte Änderung: 16.08.20 - 13:05:21 von ronka » Gespeichert

das neueste von Domino 10 auf den AdminCamp in September -> www.AdminCamp.de
Riccardo Virzi
Frischling
*
Offline Offline

Beiträge: 18



« Antworten #3 am: 16.08.20 - 16:07:25 »

Danke an Carsten und Rudi für Eure Antworten.

@Carsten: es scheint der richtige Weg zu sein, eine doppelte Konvertierung zuerst zu einem String und dann zurück in eine Zahl zu machen. Das muß ich nochmal testen und werde in den nächsten Tagen eine Rückmeldung geben.

@Rudi: ich sehe das ähnlich, intern werden manche Zahlen durch Konvertierungen leicht verändert. Das wirkt sich sehr selten auf das sichtbare Ergebniss aus.

An alle, die wie ich nur den Befehl Fix einsetzen: funktioniert ganz gut aber nicht immer. Im Forum gibt es ja einige Einträge zu dem Thema. Aber keines davon konnte mein Problem lösen. Das mit der Konvertierung in einen String und zurück in eine Zahl von Carsten, habe ich entweder nicht gesehen oder nicht verstanden.
Gespeichert
billygates
Aktives Mitglied
***
Offline Offline

Geschlecht: Männlich
Beiträge: 139


Ich kann 'proprietär' nicht mehr hören!


« Antworten #4 am: 28.08.20 - 09:30:32 »

Wie wäre es mit @Round in der Formelsprache?
Gespeichert

25 Lotus Notes R7 & R8 Server
auf Win Server & Linux Suse SLES

5500 Lotus Notes R6.5 - R8 Clients & Web Access
auf Win 2000 Prof. & Win XP Prof.
CarstenH
Senior Mitglied
****
Offline Offline

Geschlecht: Männlich
Beiträge: 311



« Antworten #5 am: 28.08.20 - 10:34:01 »

Wie wäre es mit @Round in der Formelsprache?

Die verschiedenen Programmiersprachen verhalten sich hier gleich, das ist auch in der Dokumentation so nachzulesen.
Das hatte ich auch gleich zu Beginn meines ersten Tests vorsichtshalber überprüft Wink
Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  


Einloggen mit Benutzername, Passwort und Sitzungslänge

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006, Simple Machines Prüfe XHTML 1.0 Prüfe CSS
Impressum Atnotes.de - Powered by Syslords Solutions - Datenschutz | Partner: