Das Notes Forum

Domino 9 und frühere Versionen => ND8: Entwicklung => Thema gestartet von: Gravedigger am 15.03.12 - 14:54:33

Titel: LotusScript: Format()/Round() runden Summe auf
Beitrag von: Gravedigger 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
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: Glombi 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
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: Tode 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
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: Gravedigger 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
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: ghostmw 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 ?
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: Peter Klett 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 ... :))
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: ghostmw am 16.03.12 - 08:14:40
Danke das ist durchgerutscht ...
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: Gravedigger 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
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: pram 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
Titel: Re: LotusScript: Format()/Round() runden Summe auf
Beitrag von: marschul 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.