Autor Thema: LotusScript: Format()/Round() runden Summe auf  (Gelesen 8429 mal)

Offline Gravedigger

  • Aktives Mitglied
  • ***
  • Beiträge: 179
  • Geschlecht: Männlich
LotusScript: Format()/Round() runden Summe auf
« am: 15.03.12 - 14:54:33 »
Hallo Notes Spezialisten,

ich hoffe mein Problem ist nicht zu kompliziert. Folgendes:
Wir nutzen im Unternehmen ein LotusScript Agent, welcher etliche Dokumente einliest und daraus für jedes Dokument ein XML zur Rechnungserstellung generiert. Jedes der Dokumente enthält ein Feld "fdPositions", darin sind die Beträge der Rechnungspositionen als Array, z. B. 100,00, 55,66, 154,72 usw. gespeichert.

Die Dokumente werden in einer Ansicht dargestellt. Die letzte Spalte enthält die Summe "@Sum(fdPositions)", als Beispiel 252147,10. Die Formatierung ist auf Nummer mit 2 Dezimalstellen eingestellt.

In der erstellen XML Datei wird als Summe aber 252147,14 ausgegeben. Es sind nur 4 Cent Unterschied, aber wer Buchhalter kennt, dass kann schon eine mittelschwere Katastrophe auslösen.  ;)
Mein Debugging während er XML Erstellung ergab, dass die Summe über eine For-Schleife ermittelt wird.
for i%=0 to ubound(doc.fdPositions)
sum! = sum! + doc.fdPositions(i%)
next


Lasse ich mir jetzt die Variable sum! ausgeben, erhalte ich 252147,10 in der Anzeige. Es wurde noch nichts formatiert oder gerundet!
Jetzt kommt im Agent zur Sicherheit die Formatierung per Format(sum!, "Standard") und jetzt ist die Summe 252147,14. Das Gleiche geschieht wenn anstatt Format() auf Round(sum!, 2) gewechselt wird.  ???

Und jetzt noch ein Ergebnis der Analyse: Diese Differenz tritt nur bei Rechnungssummen über 200000 auf.

Hatte jemand mit diesem "Problem" schonmal zu kämpfen? - Ich bin für jeden Hinweis dankbar.


Gruß
gravedigger
Client R 8.5.1 bis R 9.0.1 FP9 (ab Win 7 Prof.)
Server R 9.0.1 FP 6 (Win 2012 R2 Datacenter Edition x64)

Glombi

  • Gast
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #1 am: 15.03.12 - 15:19:26 »
Ich würde die Summe bereits im Dokument in einem extra Feld berechnen und in der Ansicht in der Summenspalte nur das Feld anzeigen.

Andreas

Offline Tode

  • Moderatoren
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 6.873
  • Geschlecht: Männlich
  • Geht nicht, gibt's (fast) nicht... *g*
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #2 am: 15.03.12 - 16:06:13 »
Diesen Fehler kenne ich: Das Problem ist ein Bug in Round / Format und hat damit zu tun, dass in einem PC die Zahlen immer Binär gespeichert sind, und deshalb IMMER eine Umrechnung passieren muss...
Hier zwei Dokumente von IBM zu dem Thema: Wird nicht gefixt werden... Aber wenigstens ist im zweiten link ein Workaround...
http://www-01.ibm.com/support/docview.wss?uid=swg1LO49377
https://www-304.ibm.com/support/docview.wss?uid=swg21210270
Gruss
Torsten (Tode)

P.S.: Da mein Nickname immer mal wieder für Verwirrung sorgt: Tode hat NICHTS mit Tod zu tun. So klingt es einfach, wenn ein 2- Jähriger versucht "Torsten" zu sagen... das klingt dann so: "Tooode" (langes O, das r, s und n werden verschluckt, das t wird zum badischen d)

Offline Gravedigger

  • Aktives Mitglied
  • ***
  • Beiträge: 179
  • Geschlecht: Männlich
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #3 am: 15.03.12 - 17:19:31 »
Hallo,

Danke für die Antworten. Dann werde ich morgen mal den Workaround umsetzen.
Bin auf das Ergebnis sehr gespannt.


Schönen Abend und Gruß
gravedigger
Client R 8.5.1 bis R 9.0.1 FP9 (ab Win 7 Prof.)
Server R 9.0.1 FP 6 (Win 2012 R2 Datacenter Edition x64)

Offline ghostmw

  • Aktives Mitglied
  • ***
  • Beiträge: 201
  • Geschlecht: Männlich
    • BELOS - Raum+Ressourcenmanagement unter Lotus Notes
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #4 am: 16.03.12 - 07:57:11 »
Moin,

ich hätte da vielleicht eine andere Variante, die dir vielleicht helfen könnte.


1. ) Man multipliziert die Zahl mit der n-ten Zehnerpotenz (n = Anzahl Stellen hinter dem Komma, negative Werte = Anzahl Stellen vor dem Komma)
2. ) Man addiert 0.5 zu dem Ergebnis
3.) Führt auf das Ergebnis  ein @Integer (Formel) oder Fix (LotusScript) aus
4.) nun dividiert man das Ergebnis durch die n-te Zehnerpotenz (n=Anzahl Stellen hinter dem Komma)

5.) Fertig gerundetes Ergebnis



Beispiel:

Zahl = 0.15
n = 1 Stellen hinter dem Komma

E1 = 0.15 * 10^1 = 1.5
E2 = 1.5 + 0.5 = 2
E3 = @Integer/Fix  ( 2 ) = 2
E4 = 2 / 10^2 = 0.2

e voilá

Vielleicht kann dir das helfen ?
Grüße
Marco Weller
Lotus Domino / Lotus Notes seit 1996 (ab 4.5x)

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #5 am: 16.03.12 - 08:10:53 »
Sorry, dass ich klugsch ...

E4 = 2 / 10^1 = 0.2

Bei der letzten Zeile hast Du Dich vertippt. Ansonsten eine schicke Formel.

(Für die, die nur kopieren ... :))

Offline ghostmw

  • Aktives Mitglied
  • ***
  • Beiträge: 201
  • Geschlecht: Männlich
    • BELOS - Raum+Ressourcenmanagement unter Lotus Notes
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #6 am: 16.03.12 - 08:14:40 »
Danke das ist durchgerutscht ...
Grüße
Marco Weller
Lotus Domino / Lotus Notes seit 1996 (ab 4.5x)

Offline Gravedigger

  • Aktives Mitglied
  • ***
  • Beiträge: 179
  • Geschlecht: Männlich
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #7 am: 19.03.12 - 14:57:12 »
Hallo,

vielen, vielen Dank für eure Antworten. Mit dem Workaround von IBM haben wir das Ziel erreicht.


Gruß
gravedigger
Client R 8.5.1 bis R 9.0.1 FP9 (ab Win 7 Prof.)
Server R 9.0.1 FP 6 (Win 2012 R2 Datacenter Edition x64)

Offline pram

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.169
  • Geschlecht: Männlich
    • Foconis Object Framework
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #8 am: 19.03.12 - 22:23:15 »
Zur Info: Es ist meiner Meinung nach kein Bug, sondern "works as designed".  ;D

Es gibt 2 Rundungsverfahren: Das mathematische und das kaufmännische.
http://de.wikipedia.org/wiki/Rundung#Mathematische_Rundung

Dadurch werden beim Addieren vieler (gerundeter) Zahlen die Fehler besser heraus gemittelt. Nur ist dieses im Finanzumfeld unbrauchbar.

Gruß
Roland
Roland Praml

IBM Certified Application Developer - Lotus Notes and Domino 8
Ich verwende das Foconis Object Framework

Offline marschul

  • Senior Mitglied
  • ****
  • Beiträge: 280
  • Geschlecht: Männlich
Re: LotusScript: Format()/Round() runden Summe auf
« Antwort #9 am: 15.05.12 - 10:21:44 »
So, jetzt hat mich das hier so oft diskutierte Thema "Runden" auch erwischt, denn eine Kollegin hat in einem Zins- und Tilgungsplan entdeckt, dass bei einer "glatten" 5 als dritte Dezimalstelle gelegentlich an der 2. Nachkommastelle abgerundet wird.

Also habe ich den Vorschlag von Marco aufgegriffen und in einer Klasse eine Funktion wie folgt erstellt:

Code
Private Const conModule = "clsRound."
Public Class clsRound
...	div. Private & Public Properties + Sub New ...

Public Function roundValue(Byval dInputValue As Double, Byval iDigits As Integer) As Boolean
	On Error Goto processError
	
	Dim sMethod As String
	sMethod = "roundValue: "
	roundValue = False
	
	Dim dTmpVal1 As Double, dTmpVal2 As Double, dTmpVal3 As Double, dDigits As Double, dAdd As Double
	dDigits = 10^iDigits
	dAdd = 0.50
	dTmpVal1 = dInputValue * dDigits
	dTmpVal2 = dTmpVal1 + dAdd
	dTmpVal3 = Fix(dTmpVal2)
	dResult = dTmpVal3 / dDigits
	
	roundValue = True

exitFunction:
	Exit Function
	
processError:
	sErrorString = conModule & sMethod & " Allgem. Fehler: " & Str(Err) & " " & Error$ & " Zeile: " & Str(Erl)
	Resume exitFunction
	
End Function	'roundValue
...End Class

Die vielen Zwischenvariablen sind erst nach und nach entstanden, denn das Ergebnis stimmte leider nicht immer :(

Bei einem übergebenem Wert 322.194,925 wurde richtigerweise 322.194,93 zurückgegeben.
Für 285.146,225 erhielt ich jedoch 285.146,22!

Diverse Prints zeigten folgende Werte:

dInputValue = 285146,225
dTmpVal1 = 28514622,5
dTmpVal2 = 28514623
dTmpVal3 = 28514622
dResult = 285146,22

D.h. bei dem Fix() wurde die scheinbare Ganzzahl ...23 auf ...22 geändert. Diverse Eingriffe (z.B. statt 0.5 eine Addition mit 1/2 etc.) haben nix gebracht.
Ein Print von Fraction(dTmpVal2) zeigte dann unerwartet statt ,0 einen Wert von ,999999967usw.

Unschöne, aber funktionierende Lösung:
Code
dTmpVal = Cdbl(Cstr(dTmpVal1 + dAdd))
Das Parsen in einen String und wieder zurück in einen Double sorgt bei allen Werten für korrekte Ergebnisse.
Gruß
Marco

Ich, der ich weiß, mir einzubilden, dass ich weiß, nichts zu wissen, weiß, dass ich nichts weiß. (Sokrates)
Keiner ist unnütz, er kann immer noch als schlechtes Beispiel dienen. (unbekannt)

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz