Das Notes Forum

Domino 9 und frühere Versionen => ND6: Entwicklung => Thema gestartet von: andrew22 am 10.06.05 - 00:04:09

Titel: Datum und Zeitbrechnung
Beitrag von: andrew22 am 10.06.05 - 00:04:09
hi ho !

ich habe in einer Maske 4 Felder : Startdatum , Startzeit , Enddatum , Endzeit -> alles Notes Datumsfelder.

Dieser Werde werden in einem Agent eingelesen und zwar in einer jeweils dafür deklarierte Stringvariable.

Bsp : Dim startdatum As String
startdatum = doc.GetITem........

ich muss nun berechnen wieviel Stunden und Minuten zwischen Start und End Datum / Zeit sind

also Bsp :

05.05.2005 13:30:00 - 06.05.2005 19:45:00

Ich brauche nun die Dauer und zwar Stunde und Minute also sprich keine ahnung nur als Beispielen 25 Stunden und 30 min.

hab keine ahnung wie ich das am besten machen kann

hoffe auf hilfe ;)

g8
Titel: Re: Datum und Zeitbrechnung
Beitrag von: TMC am 10.06.05 - 00:14:52
Bsp : Dim startdatum As String

Deklariere das besser nicht als String, sondern als Variant.

Es gibt eine Date-Klasse in LS, aber oft braucht man die gar nicht.
Nimm einfache Operatoren (<, >, etc.).

Hier ist schonmal eine Liste von mir:
http://www.atnotes.de/index.php?topic=17738.0

Wenn Du noch Fragen hast, sag Bescheid  ;)
Matthias
Titel: Re: Datum und Zeitbrechnung
Beitrag von: koehlerbv am 10.06.05 - 00:16:27
Zwei Fragen:
Warum berechnest Du die Zeitdifferenz nicht gleich in der Maske ?
Steht in den Time-Felder wirklich nur ein Zeitwert oder auch dort ein Datums-/Zeitwert ?

Bernhard
Titel: Re: Datum und Zeitbrechnung
Beitrag von: andrew22 am 10.06.05 - 00:18:36
das sind Datumsfelder . Notes Datumsfelder wo man nur auf diese Kleine Uhr klickt.

also irgendwie weiss ich immer noch net wie ich das machen soll :(
Titel: Re: Datum und Zeitbrechnung
Beitrag von: TMC am 10.06.05 - 00:23:23
Einfach die beiden Datumswerte (Variants, entspricht Date/Time wenn Du als Basis die ItemValues nimmst) voneinander abziehen.
Das Ergebnis entspricht Tage. Eine Stunde ist also 1/24.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: andrew22 am 10.06.05 - 00:25:33
das heißt ich soll Enddatum - Startdatum rechnen ???

und Starttime und Endtime ist egal ?!?!?
Titel: Re: Datum und Zeitbrechnung
Beitrag von: TMC am 10.06.05 - 00:29:13
Das kann jetzt unter Umständen gefährlich werden, weil in den Zeitfeldern ein Datum hinterlegt sein kann.

Am besten setzt Du Dir das Datum erstmal zusammen:
vStart = Fix(vStartDatum) + Fraction(vStartZeit).

Das gleiche mit dem Ende-Datum / Uhrzeit.

Die beiden Ergebnis-Variablen vergleichst Du dann:
vResult = vEnd - vStart

vResult kannst Du dann auswerten.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: koehlerbv am 10.06.05 - 00:54:04
Wichtig ist noch die Rundung, sonst kommt da leicht ein "unscharfer" Wert heraus:

Code
	Dim docCurrent As NotesDocument
	Dim vStartDT As Variant
	Dim vEndDT As Variant
	Dim dblResult As Long

	Set docCurrent = do it your way
	vStartDT = Fix (docCurrent.StartDate (0)) + Fraction (docCurrent.StartTime (0))
	vEndDT = Fix (docCurrent.EndDate (0)) + Fraction (docCurrent.EndTime (0))
	
	dblResult = Round ((vEndDT - vStartDT) *24 * 60, 0)
	
	Messagebox dblResult
Titel: Re: Datum und Zeitbrechnung
Beitrag von: TMC am 10.06.05 - 22:58:59
Wichtig ist noch die Rundung, sonst kommt da leicht ein "unscharfer" Wert heraus:

@Bernhard: Date/Time - Behandlung mach ich eher selten, daher interessehalber die Nachfrage: Was kommt da "unscharf" raus?
Ich hätte jetzt eigentlich gemeint, mit den Funktionen Fix und Fraction und der Addition beider Values ist dann alles im grünen Bereich.

Matthias
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 10.06.05 - 23:13:49
Die Unschärfe ist in einem anderen Bereich zu suchen, mit Deinen Methoden trennst Du sauber Datums- und Zeitwerte und eliminierst allfällige von Notes hineingebastelte Standardwerte für die Felder, die nur das eine oder das andere berücksichtigen.

Bernhard rundet dann auch noch das Endresultat. Unschärfe kann dort durch das Rundungsproblem des Prozessors entstehen, da die Register nur endliche Grösse haben. Bernhards Schlussrundung schärft das schätzungsweise zu etwa 80%, um das noch ein wenig höher zu schrauben, müsste man mit einem Epsilon-Wert arbeiten und die Rundung noch ein wenig weiter "rechts" ansetzen. Ansonsten ist das genau das Thema, wo Bernhard sonst immer von mir Beweise verlangt .........  :P ..... Also Bernhard, beweise mal, warum die Rundung notwendig ist ....  ;D
Titel: Re: Datum und Zeitbrechnung
Beitrag von: koehlerbv am 11.06.05 - 00:53:29
Hallo Matthias,

ich arbeite in etlichen Projekten exzessiv mit Datum-/Zeit-Werten (Beispiel Zeiterfassung, bei der nun wirklich nichts schiefgehen darf) , ich weiss also, wovon ich rede. Jens hat es im ersten Teil seines Postings schon gut beschrieben: Der Prozessor kann nur endlich viele Stellen verarbeiten, und DT-Angaben werden als Datumsseriennummern gespeichert. Gerade der durch Fraction herausgefilterte Bruchteil (!) des Tages kann dazu führen, das weitere Rechenoperationen mit diesem Wert, die eigentlich ganze Zahlen ergeben sollten (hier: Minuten), doch wieder reelle Zahlen ergeben. Um dies nachzuvollziehen (gerade, wenn man keine reellen Datenreihen zur Verfügung hat), braucht man sich nur entsprechende Datenreihen generieren.

Bernhard
Titel: Re: Datum und Zeitbrechnung
Beitrag von: TMC am 11.06.05 - 20:29:42
Hi Bernhard,

sorry, aber ich verstehe immer noch nicht ganz, warum hier eine Rundung erforderlich ist.

Die Designerhelp zu Fraction sagt ja auch:
Zitat
Tip  It is always true that Fix(numExpr) + fraction(numExpr) = numExpr.

Was ja indirekt aufgrund Deiner Vorgehensweise heißen würde, man müsste Date/Time-Werte generell runden nach deren Bearbeitung, also unabhängig davon ob man das nun mit Fix/Fraction zusammensetzt oder nicht.

Wäre schön wenn Du als "Beweis" ein Beispiel nennen könntest. Wäre sicherlich auch für andere hilfreich, die sich mit Date/Time rumschlagen.

Danke,
Matthias
Titel: Re: Datum und Zeitbrechnung
Beitrag von: koehlerbv am 12.06.05 - 01:03:12
Hallo Matthias,

es geht hier nicht um das Problem, Datum-/Zeitwerte generell runden zu müssen, sondern um den Umgang von Notes (bzw. prinzipiell: Den begrenzten Möglichkeiten, in einem binären System reelle Zahlen abzubilden) mit reellen Zahlen.

Heute (12.06.2005) früh um 8 Uhr liefert @Now oder in LS Now die Datumsseriennummer 38515,3333333333 zurück. Wir reden hier ja darüber, Operationen mit derartigen gebrochenen Zahlen (mit denen wiederum Operationen ausgeführt werden) wieder auf ganze Zahlen sicher zurückzuführen. Sicher heisst da für mich: Round mit den entsprechenden Parametern liefert mir wieder eine Ganzzahl, die ich dringend brauche. Diese Sicherstellung muss zudem an der frühestmöglichen (Rechen-)Operationsstelle erfolgen (logischerweise, da es ansonsten ggf. mit jedem Rechenschritt immer schlimmer wird).

Ich zitiere nochmals Semeaphoros, der genau das formuliert hat, was auch ich für sichere Programme an dieser Stelle für erforderlich halte:
Unschärfe kann dort durch das Rundungsproblem des Prozessors entstehen, da die Register nur endliche Grösse haben. Bernhards Schlussrundung schärft das schätzungsweise zu etwa 80%, um das noch ein wenig höher zu schrauben, müsste man mit einem Epsilon-Wert arbeiten und die Rundung noch ein wenig weiter "rechts" ansetzen.
Das nach "rechts verschieben" kann man sich aber angesichts der möglichen Unschärfen dank Round aber getrost schenken - wichtig ist das ergebnisnächste Runden ("ergebnisnah" heisst für mich hier: Genau an der Stelle, an der die Unschärfe auftreten kann).

Bernhard
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 01:40:43
Vorschlag (evtl. naiv) kannst du nicht eine Skriptlibrary erstellen.
In Pseudocode und die Variablennamen stimmen vermutlich auch nicht:

Name: SafeMath
Code
function division(divisor as Integer, dividend as Integer, round As Integer) As Double
division = dividend/divisor
division = round (division, round)
end function
etc...
Und die problematischen Rechenoperationen grundsätzlich über diese Funktionen laufen lassen. Klasse geht natürlich auch.

Gruß Axel
 
Titel: Re: Datum und Zeitbrechnung
Beitrag von: koehlerbv am 12.06.05 - 02:00:41
Das ist ganz sicher gar keine schlechte Idee, Axel. Nur die Datentypen sind unpassend (Integer als Übergabewert und als Ergebnis Double). Ich sehe aber gerade, dass ich in meinem Code-Beispiel auch den Fehler gemacht habe, das erwünschte ganzzahlige Ergebnis einer Double-Variablen zuzuweisen - was natürlich kontraproduktiv ist.

Bernhard
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 12.06.05 - 11:06:55
Axel, wenn es eine allgemein gültige Lösung gäbe, wäre diese schon längstens in den Programmiersprachen oder unterdessen möglicherweise bereits auf Professorebene implementiert. Kurz zusammengefasst ist das Problem mit einer solche Lösung etwa so zu umschreiben:

Diese Korrektur geht davon aus, dass der Ist-Wert von einem korrekten Soll-Wert um ein Delta abweicht. Die Korrektur versucht nun, dieses Delta zu reduzieren (ein eliminieren ist leider nicht möglich). Dabei ist der korrekte Sollwert ja nicht wirklich bekannt, sondern wird vermutet. Leider kann dabei passieren, dass das Delta statt verkleinert auch vergrössert wird. Werden nun solche mit einem Fehler behafteten Operationen aneinandergehängt, dann zeigt sich das Phänomen der Fehlerfortpflanzung. Mit jeder neuen, korrigierten Operation wird die Fehlerwahrscheinlichkeit auch grösser. Von da kommt die ziemlich strikte Regel, dass solche Korrekturen erst am Endresultat vorzunehmen sind.

Soviel zum allgemeinen, im Speziellen für Zeit und Datum spricht das ganze dafür die NotesDateTime Klasse zu verwenden, anstatt die Berechnungen direkt am Zeitwert durchzuführen, in der Hoffnung, dass die interne Implementation dieser Klasse die Problematik so weit wie möglich berücksichtigt.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 11:16:38
Jens.
Ich spreche nicht von einer allgemeingültigen Lösung. Bin mir aber ziemlich sicher, dass du in dem Falle von Bernhard eine Menge special-rundungs-math-code in eine spezielle Klasse auslagern kannst. Die mathematischen Operationen über diese Klasse werden natürlich mehr Prozessorenzyklen beanspruchen als einfach mit double zu arbeiten.
Wenn du aber in bestimmten Anwendungsfällen 0.0002 Milisekunden pro mathematische Operation verlierst, dafür aber dein code übersichtlicher wird und du weniger Fehler beim programmieren dieser Logik machst, kann es Sinn machen.

Z.B. gibt es ja in SQL auch den Datentyp Decimal, wo *diese* Floating point Rundungsfehler nicht auftauchen, da du eine fixe Anzahl an Dezimalstellen angeben kannst.

In Java gibt es z.B. die Klasse BigDecimal, die man für Fälle benutzen kann, wo floating point Rundungsfehler problematisch sind:
http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html

Ich werd mal so weit ich es verstehe eine simple Klasse für Bernhards Fall erstellen und ihr entscheidet, ob das jetzt Sinn macht oder nicht.

AFAIK existiert z.B. in einigen Bereichen der Finanzmathematik die fixe Konvention, dass alle reele Zahlen auf 5 Stellen hinter dem Komma gerundet werden, bevor Operationen mit ihnen ausgeführt werden. 100% genau ist das natürlich auch nicht. Aber Bernhard benötigt ja auch nicht eine perfekte Genauigkeit, sondern einfach nur eine andere Unschärfe als die im Kontext von floating point.


später Axel
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 11:31:00
Man kann wesentlich genauere und größere Zahlen als double speichern. Nur eben nicht im Registerspeicher, sondern im Heap Speicher.
Theoretisch müßte es möglich sein einen Großteil des Heap-Speichers zur Definition einer einzigen Zahl zu verwenden. Nur sind dann die Operationen mit dieser Zahl nicht so besonders schnell.
Natürlich ist die Genauigkeit der Zahl dann auch durch die eingesetzte Hardware eingeschränkt. Man kann aber das Genauigkeitsconstraint nach außen verschieben.
Oder man benutzt eine *andere* Unschärfe wie z.B. in Decimal.

Axel
Titel: Re: Datum und Zeitbrechnung
Beitrag von: animate am 12.06.05 - 11:34:40
ich sehe ehrlich gesagt keinen Grund, nicht die NotesDateTime-Klasse zu benutzen.
Kann mir das jemand mal erläutern, bitte?

Tipp:

erstelle zwei NotesDateTime-Objekte mit deinen beiden Daten und ermittle deren Differenz (TimeDifferenceDouble - Methode). Dann bekommst du das auf die Sekunde genaue Ergebnis in Sekunden und kannst es in ein Format deiner Wahl umrechnen (hh:mm, z.B.) und musst dich nicht mit runden, reellen Zahlen, Unschärfe, etc. beschäftigen.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 12.06.05 - 12:09:25
Thomas, volle Zustimmung, das war der Inhalt meines letzten Satzes.

Axel, wenn ich die BigDecimal Defintion richtig gelesen habe, ist das ebenfalls ein Float-Datentyp, der hat im Prinzip genau die gleichen Probleme, vermutlich einfach durch höhere Genauigkeit für die Praxis etwas entschärft.

Was bei Oracle der Decimal-Datentyp genau ist, weiss ich nicht. Ich vermute mal, dass es sich um einen BCD-Datentyp handelt. Der zeigt das Phänomen natürlich deutlich weniger als irgend ein rein binärer Datentyp, hat dafür andere Einschränkungen und leidet vor allem an der Effizienz. Und -- in LotusScript bzw. Notes/Domino gibts den Typ nicht, kommt also geradezu nicht in Frage.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 12:24:42
Der Trick ist, dass du festlegen kannst nach wie vielen Stellen hinter dem Komma gerundet wird (mit scale-property). Ausserdem kannst du die Rundungsmethode wählen.
Präferiere: "auf eine klar definierte Art und Weise entschärft" gegenüber "etwas entschärft"  ;D. Es ist schon klar, dass man 1/3 nicht wirklich genau als Dezimalzahl oder Binärzahl wiedergeben kann.

Wobei ich mir bei einem Beispiel gerade in den Fuß geschossen habe:
Es zeigt genau das umgekehrte von dem, was ich beweisen wollte  ::)
Code
// use ide to import classes
public class ASimpleMathQuestion {

	public static void main(String[] args) {
		System.out.println("a simple math task for my computer...\na) using double: (1 / 3) * 3=" + ((1/3) + 3));
		System.out.print("a simple math task for my computer...\nb) using BigDecimal: (1 / 3) * 3=");
		BigDecimal anOne = new BigDecimal(1);
		BigDecimal aThree = new BigDecimal(3);
		System.out.println(aThree.multiply(anOne.divide(aThree, 100, BigDecimal.ROUND_HALF_DOWN)));
		
	}
}
Ergibt:
Code
a simple math task for my computer...
a) using double: (1 / 3) * 3=3
b) using BigDecimal: (1 / 3) * 3=0.9999999999999999999999999999999999999999
Naja. Es ist eine andere Art von Unschärfe. Muß das wohl noch ein bischen üben mit BigDecimal. Ich kann mich dunkel daran erinnern, dass in Finanzmathematik intern auf 5 Stellen hinter dem Komma gerechnet wird und auf 2 oder 3 Stellen hinter dem Komma angezeigt wird.

Wenn man den Anzeigewert setScale(scaleInter-1) gibt gehts:
Code
public class ASimpleMathQuestion {

	public static void main(String[] args) {
		 
		System.out.println("a simple math task for my computer...\na) using double: (1 / 3) * 3=" + ((1/3) + 3));
		System.out.print("b) using BigDecimal: (1 / 3) * 3=");
		BigDecimal anOne = new BigDecimal(1);
		BigDecimal aThree = new BigDecimal(3);
		int scale = 40;
		System.out.println(aThree.multiply(anOne.divide(aThree, scale, BigDecimal.ROUND_HALF_DOWN)).setScale(scale-1, BigDecimal.ROUND_HALF_DOWN));
		
	}
}
ergibt:
Code
a simple math task for my computer...
a) using double: (1 / 3) * 3=3
b) using BigDecimal: (1 / 3) * 3=1.000000000000000000000000000000000000000
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 12:30:04
Was bei Oracle der Decimal-Datentyp genau ist,
Imho ist es ein SQL92 Datentyp. Ist nicht Oracle spezifisch.
Zitat
weiss ich nicht. Ich vermute mal, dass es sich um einen BCD-Datentyp handelt.
Es ist - wie BigDecimal - nicht floating point.
Man gibt die Anzahl der Ziffern hinter dem Komma fix an und gleichzeitig die Regeln für die Rundung (s. mein Beispiel f. BigDecimal).
Zitat
Und -- in LotusScript bzw. Notes/Domino gibts den Typ nicht, kommt also geradezu nicht in Frage.
Meine Idee ist, diesen Datentyp nachzuprogrammieren, was geht.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: TMC am 12.06.05 - 17:50:15
im Speziellen für Zeit und Datum spricht das ganze dafür die NotesDateTime Klasse zu verwenden, anstatt die Berechnungen direkt am Zeitwert durchzuführen, in der Hoffnung, dass die interne Implementation dieser Klasse die Problematik so weit wie möglich berücksichtigt.

ich sehe ehrlich gesagt keinen Grund, nicht die NotesDateTime-Klasse zu benutzen.

Bis gestern war ich eigentlich der Meinung, für so simple Dinge braucht man die Klasse nicht.

Aber aufgrund der hier geschilderten Probleme werde ich zukünftig sicherlich primär die DateTime-Klasse benutzen (oder eine eigene Klasse, die auf die DT-Klasse aufsetzt), und nicht mehr eigenständig hier rumhantieren, die Gefahr ist wohl zu groß, dass da was schief läuft, und prinzipiell muss man sich auf die DT-Klasse auch verlassen können (wie eben auf jede andere Klasse auch – Bugs sind natürlich nie ganz auszuschließen).

Matthias
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 21:08:53
Es haben sich hier verschiedene Themen vermischt. Wobei ich daran natürlich nicht ganz unschuldig bin.
Das mit Bernhards Rundungsfehler hat ja nicht unbedingt etwas mit Zeit und Datumsberechnung zu tun, sondern mit seiner speziellen Implementierung einer Lösung und der sich daraus ergebenen Problematiken.
Das mit der fixen Anzahl an Stellen hinter dem Dezimalpunkt ist aber auch ein wichtiger Punkt. Zumindest für mich. Deshalb werd ich eine entsprechende fixedDecimalPointMath Klasse mal erstellen.
@Jens: ich hab noch mal gegoogelt. Das hat wirklich nix mit BCD-Datentyp zu tun.
Wenn ich die entsprechende Klasse geschrieben habe, wird das - denke ich - klar.
LotusScript hat übrigens einen numerischen "fixed point" Datentyp. Currency. Selten benutzt, aber das ist die Richtung, die ich meine.

Axel
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 12.06.05 - 21:28:42
Sorry, Axel, Currency ist Float mit einer besonderen Darstellungsart, genauso wie Deine Math-Klasse am Schluss schlichtweg eine Extension zu einem bestehenden, anderen Datentyp sein wird. Currency wird intern genau gleich wie Float repräsentiert.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 22:22:05
imho besteht der Unterschied darin, dass Currency nach jeder Operation automatisch auf 4 Stellen hinter dem Komma rundet und das macht Float nicht.
Das ist aus meiner Sicht der Unterschied. Nicht ob das jetzt intern als Float repräsentiert wird oder nicht.
Bei currency gibt es implizit immer einen Round(floatErgebnis, 4-Stellen).
Und das macht einen Unterschied.


Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 22:35:54
Ich glaub auch ehrlich gesagt nicht, dass BigDecimal intern einen double oder float implementiert.
http://www.galileocomputing.de/openbook/javainsel/java-05.htm#t312
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 12.06.05 - 22:38:45
imho besteht der Unterschied darin, dass Currency nach jeder Operation automatisch auf 4 Stellen hinter dem Komma rundet und das macht Float nicht.

Mein lieber Freund und Kupferstecher, wenn das der Fall wäre, wäre das die absolute Katastrophe und Iris wäre seinerzeit mit Protesten überhäuft worden. Eine solche Implementation ist nahe daran als Zufallsgenerator gebraucht zu werden.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: koehlerbv am 12.06.05 - 22:40:11
Das mit Bernhards Rundungsfehler ...

Axel, ich habe keine Probleme mit Rundungsfehlern - ich habe nur versucht, andere davor zu bewahren  ;)

... Rundungsfehler hat ja nicht unbedingt etwas mit Zeit und Datumsberechnung zu tun, sondern mit seiner speziellen Implementierung einer Lösung und der sich daraus ergebenen Problematiken.

Das sehe ich ganz genauso. Die Rechengenauigkeit eines binären Systems ist immer endlich, daher habe ich mir angewöhnt, auf jeder Berechnungsstufe sicherzustellen, dass die gewünschte Dimension auch zur Verfügung steht und sich eben keine "Unschärfe" einschleichen kann. Und das betrifft selbstverständlich nicht nur Operationen mit Datumsseriennummern - das kann hier ja nur als Beispiel dienen.

Bernhard
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 22:41:09
faq comp.lang.java argumentiert auch in meine Richtung:
Zitat
In einem Computer sind natürlich nur endlich viele Gleitkommazahlen
darstellbar. In der Mathematik gibt es aber unendlich viele. Will man also
das mathematische Rechnen auf einem Computer 'simulieren', muss man
ständig versuchen, trotz dieses Umstandes möglichst nahe an den 'wahren'
Werten zu bleiben. Dieses Auswählen eines geeigneten Stellvertreters unter
den im Rechner darstellbaren Zahlen ist es, was man, allgemein gesprochen,
'Runden' nennt, und diese Operation ist im Grunde vor und nach jeder
arithmetischen Operationen notwendig, wenn man sicherstellen will, dass
die Gesetze der Mathematik nicht verletzt werden. Die bekanntesten Arten
zum Runden sind: den 'oberen' Nachbarn, den 'unteren' Nachbarn oder die
'nächstliegende' Zahl im System der darstellbaren Gleitkommazahlen
auszuwählen.
http://www.faqs.org/faqs/de/comp-lang-java/faq/
Titel: Re: Datum und Zeitbrechnung
Beitrag von: koehlerbv am 12.06.05 - 22:43:10
Nicht schlecht formuliert  :)
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 22:57:53
Currency rundet wohl nach jeder Operation.  :-:
Zumindest kann ich mir die Ergebnisse dieses Skriptes nicht anders erklären.

Code
Sub Initialize
	Dim cur As Currency
	Dim dob As Double
	Dim curSum As Currency
	Dim dobSum As Double
	
	cur = 1/3
	Print "cur=" & Cstr(cur)
	dob = 1/3 
	Print "dob=" & Cstr(dob)
	
	curSum = 0
	dobSum = 0
	
	For i=0 To 1000 
		curSum = curSum + cur 
		dobSum = dobSum + dob
	Next
	
	Print "curSum=" & Cstr(curSum)
	
	Print "dobSum=" & Cstr(dobSum)
	
	
	
End Sub

Ergibt für cur ,3333, für double ,333333333333333
Jetzt könntest du noch argumentieren, dass diese 4 Stellen nur eine externe Darstellungsformel ist, die von der (genaueren) internen Darstellung abweicht. Das ist aber nicht der Fall.
Die Ergebnisse der Schleife mit den 1000 Aditionen kommen zu unterschiedlichen Ergebnissen, die ich mir nur dadurch erklären kann, dass bei currency zum Abschluss jeder Operation auf 4 Stellen hinter dem Komma gerundet wird:
curSum ergibt: 333,6333
doubleSum ergibt: 333,666666666665
Beide Zahlen unterscheiden sich ab der 2. Dezimalstelle relativ stark und das kommt eben dadurch, dass bei currency zum Abschluß jeder Operation auf 4 Stellen gerundet wird.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 12.06.05 - 23:02:55
Gerade nachgeschaut, entgegen der ursprünglichen Basic-Definition implementiert LS Currency als Integer (was, da es dokumentiert ist, auch zulässig ist). Von Runden steht da nichts, das wird nach der 4. Stelle abgeschnitten.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 23:03:23
Noch besser:
Hier habe ich das von mir für Currency behauptete Verhalten für Double nachprogrammiert.
Die Empirie ist auf meiner Seite:
Code
Sub Initialize
	Dim cur As Currency
	Dim dob As Double
	Dim dobRounded As Double
	
	Dim curSum As Currency
	Dim dobSum As Double
	Dim dobRoundedSum As Double
	
	
	cur = 1/3
	Print "cur=" & Cstr(cur)
	dob = 1/3 
	Print "dob=" & Cstr(dob)
	dobRounded = Round(1/3, 4)
	Print "dobRounded=" & Cstr(dobRounded) 
	
	curSum = 0
	dobSum = 0
	
	For i=0 To 1000 
		curSum = curSum + cur 
		dobSum = dobSum + dob
		dobRoundedSum = Round(dobRoundedSum + dobRounded, 4)
	Next
	
	Print "curSum=" & Cstr(curSum)
	
	Print "dobSum=" & Cstr(dobSum)
	Print "dobRoundedSum=" & Cstr(dobRoundedSum)
	
	
	
End Sub
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 23:06:25
Abschneiden ist imho auch eine Form des Rundens.
Die Behauptung, currency würde nach einer anderen Rundungsregel funktionieren als
Round(val, 4), fänd ich angesichts des letzten von mir geposteten Agenten ein bischen stur.
Code
Dim cur as Currency
cur = 2/3 
ergibt 0,6667
würde nach der 4. Stelle abgeschnitten, müßte es 0,6666 ergeben.

Ich kann mich auch von einem Finanzmathematik Kurs in der Uni erinnern, dass da runden-nach-jeder-Operation etwas völlig normales ist.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 12.06.05 - 23:24:43
Currency rundet tatsächlich. Da gibts 2 Bemerkungen dazu: zum einen steht das so nicht in der Hilfedatei (wenigstens bei mir nicht), was eine sehr unglückliche Nachlässigkeit darstellt, zum andern ist mir jetzt klar geworden, warum viele alte Hasen immer wieder vor dem Gebrauch des Datentyps Currency warnen. Dies in den Ohren hab ich ihn tatsächlich bisher nie verwendet. Werde dies mit Sicherheit auch in Zukunft nicht tun, dieses Verhalten ist schon recht problembehaftet.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 12.06.05 - 23:36:45
Jens. Ich kapier dein Problem mit Runden nicht, angesichts der Tatsache, dass Computer viele Elemente der unendlichen Menge der Reelen Zahlen nicht korrekt darstellen können.
Runden erscheint mir da als sinnvolle Konvention, die auch in der Finanzmathematik sehr verbreitet ist. 
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 12.06.05 - 23:54:28
Schau mal Dein erstes Script an, wer kassiert die 3 cent 33? Und das waren erst mal die Kleinigkeit von 1000 Transaktionen .....
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Semeaphoros am 13.06.05 - 00:01:31
PS: Ich hab übrigens überhaupt nichts gegen das Runden, ich hab was gegen das unüberlegte Runden und gegen das Runden im falschen Moment.
Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 13.06.05 - 00:10:47
Das double Ergebnis ist ja auch nicht "richtig". Es ist nur ein bischen genauer.


Ich hab 1001 mal 1/3 adiert.
1001 * (1/3) kann man kürzen zu:
1001/3.
Das ergibt auf dem Windows-Taschenrechner:
333,66666666666666666666666666667
Vergleich das mit den Werten oben.

Wie gesagt gibt es Bereiche in der angewandten Mathematik bestimmte Bereiche, wo per Konvention Runden am Ende der Operation ein allgemein anerkannter Standard ist.

Dann ist das Ergebnis zwar auf vielen Plattformen hinsichtlich der Genauigkeit suboptimal, aber zumindest überall reproduzierbar und nicht von unterschiedlichen Implementierung des Datentyps double abhängig.

Ich bleib übrigens bei der Hypothese, dass ich mit java.math.BigDecimal ein genaueres Ergebnis als mit double hinbekomme, aber das mach ich später.  8)

Gute Nacht

Axel

Titel: Re: Datum und Zeitbrechnung
Beitrag von: Marinero Atlántico am 13.06.05 - 00:30:06
ok. Fertig.
BigDecimal ROCKS   8) O0 8)
Code
public class ASimpleMathQuestion {

	public static void main(String[] args) {
		 
		//System.out.println("a simple math task for my computer...\na) using double: (1 / 3) * 3=" + ((1/3) + 3));
		//System.out.print("b) using BigDecimal: (1 / 3) * 3=");
		int scale = 10000;
		double dSum = 0;
		double dOneThird = (double) 1/3;
		BigDecimal anOne = new BigDecimal(1);
		
		BigDecimal aThree = new BigDecimal(3);
		BigDecimal aOneThird = anOne.divide(aThree, scale, BigDecimal.ROUND_HALF_DOWN);
		BigDecimal theSum = new BigDecimal(0);
		for (int i = 0; i<= 1000; i++) {
			theSum = theSum.add(aOneThird);
			dSum += dOneThird;
		}
		
		System.out.println("theSum (BigDecimal=" + theSum);
		System.out.println("dSum (double)=" + dSum);
		
		
		
	}
}

Ergebnis:
theSum (BigDecimal=333.<9998_mal_die_6>333 *
dSum (double)=333.66666666666515

* kann hier nicht dargestellt werden. Habs in Textpad kopiert und da waren 9998 6en nach dem Komma. Wenn ich den scale Wert noch höher als 10000 setze, dürte es noch genauer werden, aber hier gibts natürlich auch irgendwo eine Grenze.