Autor Thema: Datum und Zeitbrechnung  (Gelesen 20367 mal)

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #20 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
« Letzte Änderung: 12.06.05 - 12:49:50 von Marinero Atlántico »

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #21 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.

Offline TMC

  • Freund des Hauses!
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 3.660
  • Geschlecht: Männlich
  • meden agan
Re: Datum und Zeitbrechnung
« Antwort #22 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
Matthias

A good programmer is someone who looks both ways before crossing a one-way street.


Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #23 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
« Letzte Änderung: 12.06.05 - 21:14:23 von Marinero Atlántico »

Offline Semeaphoros

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 8.152
  • Geschlecht: Männlich
  • ho semeaphoros - agr.: der Notesträger
    • LIGONET GmbH
Re: Datum und Zeitbrechnung
« Antwort #24 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.
Jens-B. Augustiny

Beratung und Unterstützung für Notes und Domino Infrastruktur und Anwendungen

Homepage: http://www.ligonet.ch

IBM Certified Advanced Application Developer - Lotus Notes and Domino 7 und 6
IBM Certified Advanced System Administrator - Lotus Notes and Domino 7 und 6

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #25 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.



Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #26 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

Offline Semeaphoros

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 8.152
  • Geschlecht: Männlich
  • ho semeaphoros - agr.: der Notesträger
    • LIGONET GmbH
Re: Datum und Zeitbrechnung
« Antwort #27 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.
Jens-B. Augustiny

Beratung und Unterstützung für Notes und Domino Infrastruktur und Anwendungen

Homepage: http://www.ligonet.ch

IBM Certified Advanced Application Developer - Lotus Notes and Domino 7 und 6
IBM Certified Advanced System Administrator - Lotus Notes and Domino 7 und 6

Offline koehlerbv

  • Moderator
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 20.460
  • Geschlecht: Männlich
Re: Datum und Zeitbrechnung
« Antwort #28 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

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #29 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/

Offline koehlerbv

  • Moderator
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 20.460
  • Geschlecht: Männlich
Re: Datum und Zeitbrechnung
« Antwort #30 am: 12.06.05 - 22:43:10 »
Nicht schlecht formuliert  :)

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #31 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.

Offline Semeaphoros

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 8.152
  • Geschlecht: Männlich
  • ho semeaphoros - agr.: der Notesträger
    • LIGONET GmbH
Re: Datum und Zeitbrechnung
« Antwort #32 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.
Jens-B. Augustiny

Beratung und Unterstützung für Notes und Domino Infrastruktur und Anwendungen

Homepage: http://www.ligonet.ch

IBM Certified Advanced Application Developer - Lotus Notes and Domino 7 und 6
IBM Certified Advanced System Administrator - Lotus Notes and Domino 7 und 6

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #33 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

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #34 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.
« Letzte Änderung: 12.06.05 - 23:18:41 von Marinero Atlántico »

Offline Semeaphoros

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 8.152
  • Geschlecht: Männlich
  • ho semeaphoros - agr.: der Notesträger
    • LIGONET GmbH
Re: Datum und Zeitbrechnung
« Antwort #35 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.
Jens-B. Augustiny

Beratung und Unterstützung für Notes und Domino Infrastruktur und Anwendungen

Homepage: http://www.ligonet.ch

IBM Certified Advanced Application Developer - Lotus Notes and Domino 7 und 6
IBM Certified Advanced System Administrator - Lotus Notes and Domino 7 und 6

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #36 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. 

Offline Semeaphoros

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 8.152
  • Geschlecht: Männlich
  • ho semeaphoros - agr.: der Notesträger
    • LIGONET GmbH
Re: Datum und Zeitbrechnung
« Antwort #37 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 .....
Jens-B. Augustiny

Beratung und Unterstützung für Notes und Domino Infrastruktur und Anwendungen

Homepage: http://www.ligonet.ch

IBM Certified Advanced Application Developer - Lotus Notes and Domino 7 und 6
IBM Certified Advanced System Administrator - Lotus Notes and Domino 7 und 6

Offline Semeaphoros

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 8.152
  • Geschlecht: Männlich
  • ho semeaphoros - agr.: der Notesträger
    • LIGONET GmbH
Re: Datum und Zeitbrechnung
« Antwort #38 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.
Jens-B. Augustiny

Beratung und Unterstützung für Notes und Domino Infrastruktur und Anwendungen

Homepage: http://www.ligonet.ch

IBM Certified Advanced Application Developer - Lotus Notes and Domino 7 und 6
IBM Certified Advanced System Administrator - Lotus Notes and Domino 7 und 6

Marinero Atlántico

  • Gast
Re: Datum und Zeitbrechnung
« Antwort #39 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

« Letzte Änderung: 13.06.05 - 00:13:37 von Marinero Atlántico »

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz