mikrocontroller.net

Forum: PC-Programmierung Problem bei Datumsberechung


Autor: Bernd (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich möchte den Tag eines betimmten Datums berechnen. Das Bezusgsdatum 
ist der 1.1.1970. Siehe Funktion ermittle_tage(). Ich teile die Anzahl 
der Tage zwischen den Daten durch die Anzahl der Wochentage und 
ermittele den Rest dieses Quotienten in Tagen. Durch eine einfache 
if-Abfrage möchte ich so den Tag des neues Datums berechnen. Das 
funktioniert nicht bei Tagen die größer als die Anzahl der Wochentage 
sind. Ich vermute, das ich etwas bei der Typumwandlung falsch gemacht.

Danke für die Hilfe im Voraus.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> teile die Anzahl der Tage zwischen den Daten durch die Anzahl
> der Wochentage und ermittele den Rest dieses Quotienten in Tagen.

Den Rest bei einer int Division kriegt man mit %

  int i = 31;
  int j = 7;


  i / j    ->  4
  i % j    ->  3

weil:  4 * 7 + 3 == 31

Der Rest schaut sehr kompliziert aus. Such mal im Netz
nach 'Julianisches Datum'. Da gibt es eine Formel mit
der du unser heutiges Datum in eine fortlaufende Tageszahl
umrechnest.

Zuvor schau dir aber in einem C-Lehrbuch den Abschnitt
über Arrays an. Danach überlegst du dir, wie du die
Anzahl der Tage aus der Monatsnummer kriegst, wenn du
ein Array einsetzt. Damit fällt dann schon mal fast
70% deines Codes weg.

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Natürlich bin ich die Restberechung viel zu kompliziert angegangen. 
Werde ich ändern.

Meine Vorgehensweise war so.

i/j=n
31/7 = 4,42857...
n-4 = 0,428557...
0,428557... * j = 3

So in der Art müsste auch der %-operator funktionieren.

Aus dem gannzahligen Rest (hier 3) möchte ich auf den Tag zurückrechnen. 
Ich weiß, das der 1.1.1970 ein Donnerstag ist. eine Woche später ist 
wieder ein Donnerstag und eine Woche und ein Tag später ist Freitag. Das 
funktioniert nur, solange der gannzahlige Rest kleiner gleich 3 ist.

Ich muss mir das nochmal in Ruhe anschauen und das ganze auch mit einem 
Array machen

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> So in der Art müsste auch der %-operator funktionieren.

Viel simpler.
Der Rest ist entweder ein Nebenprodukt bei der eigentlichen
Division, oder er wird so berechnet:

  int i, j, Erg, Rest;

  Erg = i / j;
  Rest = i - Erg * j;

Über double rechnet man nur in Notfällen, weil dich die
Rundungsgenauigkeit umbringt. Du gehst mit deinem
mathematischen Wissen an die Dinge ran und für dich ist
es ganz natürlich, dass 3 * (1/3) wieder 1 ergibt
(oder auch, dass 10 * (1/10) wieder 1 ergibt).
Auf einem Computer ist das aber nicht so. Die haben nur
eine begrenzte Stellenanzahl. Selbst wenn du 1./3. als
double rechnest, kommt bei der Multiplikation mit 3.
da nicht mehr 1 heraus, sondern 0.999999999999was_weis_ich
Und das ist nun mal nicht 1. Wenn du diese Zahl auf
einen int zuweist, werden die Nachkommastellen abgeschnitten
und das Ergebnis ist 0 und nicht 1.
Auf einem Computer ist die Situation sogar noch schlimmer
als du es gewohnt bist. Durch das Binärsystem gibt es
wesentlich mehr Zahlen, die selbst bei noch so grosser
Bitzahl nicht exakt dargestellt werden können. 0.1 ist
zb. so ein Kandidat. 0.1 ist mit dem üblichen IEEE double
Schema nicht exakt darstellbar.

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem liegt vermutlich in der Typumwandlung.

double_quotient = (double) summe_tage / wochentage;  //Typumwandlung in 
double

Bei goßen Zahlen fällt der Rundungsfehler erst ins Gewicht.

Lässt sich der Restwert von i % j dann in einer Variablen speichern? So 
in dieser Art:

diff = (i % j) //diff = 3

Hört sich fast so an, als wenn du den %-operator selbst entwickelt hast.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd wrote:
> Das Problem liegt vermutlich in der Typumwandlung.
>
> double_quotient = (double) summe_tage / wochentage;  //Typumwandlung in
> double

Da eher weniger.
Aber du machst ja auch noch was mit dem double_quotient.

>
> Bei goßen Zahlen fällt der Rundungsfehler erst ins Gewicht.

Nicht erst bei grossen Zahlen.
Er fällt immer ins Gewicht. Und je mehr du mit double
rechnetst umso schlimmer wirds.

<Zitat>
Rechnen mit Flieskommarithmetik
ist wie das umschaufeln eines Sandhaufens.
Je öfter man es macht, desto weniger Sand
und desto mehr Schmutz hat man.
<Zitat>

>
> Lässt sich der Restwert von i % j dann in einer Variablen speichern? So
> in dieser Art:

Sicher.
Das ist ein arithmetischer Ausdruck wie jeder andere auch.

> Hört sich fast so an, als wenn du den %-operator selbst
> entwickelt hast.

Lieb von dir. Stimmt aber nicht.
Den kennst du auch. Du kennst ihn sogar schon lange!
Du hast nur nicht gewusst, dass er in C mit einem %
dargestellt wird.
Erinnerst du dich noch? "Eine Mutter hat 17 Äpfel und
3 Kinder. Wenn alle Kinder gleich viele Äpfel bekommen,
wieviele Äpfel bleiben der Mutter übrig?"
Grundschule: 3te oder 4te Klasse


Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist bei Programmiersprachen immer das Problem: eigentlich simple 
Sachen (wie das Äpfelproblem) in der jeweiligen Hochsprache zu 
implementieren.

Prinzipiell ist es immer problematisch einen Computer mit der Berechnung 
von Fließkommazahlen zu beauftragen, weil diese Zahlen ja auch nur in 
einem endlichen Speicherbereich abgelegt werden können. Das habe ich 
schon gelernt. Nur manchmal geht es halt  nicht anders.

Ein weiteres Problem ist, das man sich bei Hochsprachen schlecht 
vorstellen kann, was da im Prozessor abläuft. Oder anders ausgedückt: 
wie übersetzt der Compiler die Token in 01-Arithmetik.

Über das Zitat muss ich noch nachdenken. Von wem ist den das?

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das ist bei Programmiersprachen immer das Problem: eigentlich simple
>Sachen (wie das Äpfelproblem) in der jeweiligen Hochsprache zu
>implementieren.

Nee, ist es nicht. Man muß nur den Algorithmus wissen/herausfinden. Dann 
kann man das sogar in Assembler.

>Ein weiteres Problem ist, das man sich bei Hochsprachen schlecht
>vorstellen kann, was da im Prozessor abläuft. Oder anders ausgedückt:
>wie übersetzt der Compiler die Token in 01-Arithmetik.

Ist doch eigentlich ziemlich irrelevant, oder?
Wenn du zu einem Ergebnis kommst, von dem weisst oder zumindest der 
Meinung bist, dass es richtig ist, kann es dir doch egal sein, wie der 
Compiler das übersetzt.

Es gibt ein paar Regeln, die man beachten muß, und fertig.
Ob man das jetzt in C, Basic, Pascal oder Java programmiert, sollte 
relativ egal sein.

(Ob dieser Beitrag jetzt nötig war, sei dahin gestellt...)

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Ist doch eigentlich ziemlich irrelevant, oder?
Wenn du zu einem Ergebnis kommst, von dem weisst oder zumindest der
Meinung bist, dass es richtig ist, kann es dir doch egal sein, wie der
Compiler das übersetzt."

Du hast mich Missverstanden: Ich meinte das Problem ist zu wissen, wie 
der Compiler das Problem übersetzt und das Problem schließlich im 
Prozessor landet. Außerdem gibt es Compiler, die Probleme 
unterschiedlich übersetzen - der von Borland z.B. setzt eine strengere 
Ausformulierung des Problems voraus als der GNU.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd wrote:
> "Ist doch eigentlich ziemlich irrelevant, oder?
> Wenn du zu einem Ergebnis kommst, von dem weisst oder zumindest der
> Meinung bist, dass es richtig ist, kann es dir doch egal sein, wie der
> Compiler das übersetzt."
>
> Du hast mich Missverstanden: Ich meinte das Problem ist zu wissen, wie
> der Compiler das Problem übersetzt und das Problem schließlich im
> Prozessor landet. Außerdem gibt es Compiler, die Probleme
> unterschiedlich übersetzen - der von Borland z.B. setzt eine strengere
> Ausformulierung des Problems voraus als der GNU.

Äh. Nein
Programmiersprachen, zumindest die Ernstzunehmenden, sind
genormt. Es gibt also ein Dokument, welches genau beschreibt
was C ist und was nicht C ist. In dem Dokument ist auch
beschrieben, welche Wirkung eine Anweisung haben muss, sodass
jeder Compilerhersteller seinen Compiler dahingehend prüfen
kann. Damit muss ich aber nicht wissen, wie ein Compiler
eine bestimmte Passage übersetzt. Es reicht völlig aus zu
wissen, was auf logischer Ebene passieren muss. Wie dieses
Ziel auf Maschinenspracheebene realisiert wird, ist nicht
mein Bier.

> Über das Zitat muss ich noch nachdenken. Von wem ist den das?
Das Zitat stammt aus dem Buch:

Jim Blinn, Blinns Corner - A trip down the graphics pipeline.

Im Original geht es so

Working with floating point
is like moving piles of sand.
Each time you do it,
you loose a little sand
and pick up a little dirt.

Es stammt nicht von Blinn. Er hat es in irgendeinem Lab
bei einer Firma als Wandschmuck aufgeschnappt.

>> Das ist bei Programmiersprachen immer das Problem: eigentlich
>> simple Sachen (wie das Äpfelproblem) in der jeweiligen
>> Hochsprache zu implementieren.
>
> Nee, ist es nicht. Man muß nur den Algorithmus wissen/herausfinden.
> Dann kann man das sogar in Assembler.

Algotihmen sind ein Thema.
Ein anderes Thema ist es, seine Werkzeuge zu kennen. Dein
Werkzeug ist die Programmiersprache C. Du solltest dir die
Zeit nehmen und dir mal ein Buch darüber zulegen. Irgendwo
in den ersten 40 Seiten (von 160) wird auch auf den % Operator
eingegangen.

Ich finde es immer wieder erschreckend, wieviele Leute gerade
in diesem Forum nach den einfachsten C-Dingen fragen, die
allesamt mit einer 2-Wochen-abends-im-Bett-Lektüre vom
K&R (*) zu erschlagen sind.

Und dann kommt natürlich noch dazu, dass man als Programmierer
ein guter Beobachter sein sollte. Wir Menschen können viele
Dinge und wir machen sie unterbewusst ohne gross darüber nach-
zudenken. Ein Programmierer hat gelernt zu beobachten und
aus dem Beobachteten allgemeine Regeln oder Verfahren abzuleiten.
Man sollte es nicht glauben, wieviele Algorithmen einfach nur
Beschreibungen von Handlungsweisen sind, die jeder von uns täglich
ohne Probleme macht. Nur wenn er beschreiben soll, was er denn
gerade im Detail gemacht hat, dann können das die Wenigsten.


(*) K&R  Die übliche Kurz-Bezeichnung für
    "Kernighan & Ritchie, Programmieren in C"

Autor: Bernd (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ok danke für die Tips,

habe das Problem jetzt behoben und das Programm mit meinem Geburtsdatum 
(einem Donnerstag) getestet. Natürlich reicht dieser Test bei weitem 
nicht aus. Kommerzielle Entwickler machen das mit Grenzwertanalysen und 
vorheriger Festlegung der Äquivalenzklassen. Das Buch vom Balzert 
(Lehrbuch der SW-Technik) bechreibt einiges zu diesem Thema.

Über C habe ich folgende Bücher: H. Erlenkötter und die RRZN-Schriften 
der Uni Hannover. Die K&R-Bibel scheint abgespaced zu sein. Lohnt es 
sich diese zu kaufen?

Du meinst mit Normung der Compiler sicher den ANSI-Standard?

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die K&R-Bibel scheint abgespaced zu sein.
Finde ich nicht. Nur die erste deutsche Ausgabe ist "abgespaced", da sie 
scheinbar von einem Computer übersetzt wurde.

>Du meinst mit Normung der Compiler sicher den ANSI-Standard?
Jepp.

> Du hast mich Missverstanden: Ich meinte das Problem ist zu wissen, wie
> der Compiler das Problem übersetzt und das Problem schließlich im
> Prozessor landet.
Das kann dir doch eigentlich egal sein, solange die Logik in deinem 
Programm stimmt.

>Außerdem gibt es Compiler, die Probleme unterschiedlich übersetzen - der von 
>Borland z.B. setzt eine strengere Ausformulierung des Problems voraus als >der 
GNU.

"Verschiedene" C-Compiler kann man man mit verschiedenen Dialekten einer 
natürlichen Sprache (z.B. Deutsch) vergleichen:
Es gibt eine grundlegende Sprache, auf die man sich geeinigt hat.
Durch regionale Unterschiede gibt es gewisse Erweiterungen.
Anders ist es bei C und den verschiedenen Compilern auch.

>strengere Ausformulierung des Problems
Inwiefern? Compiler beschäftigen sich nicht mit Problemen, sondern mit 
dem Übersetzen von einer Sprache in eine andere - quasi Dolmetscher.
Im Regelfall wird eine Hochsprache in Maschinencode übersetzt - irgendwo 
habe ich mal einen Basic-C-Compiler gesehen, der aus einem 
Basic-Quellcode C-Quellcode gemacht hat...

Autor: Captain Core (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs doch mit der DOOMSDAY-Regel (siehe Wikipedia)

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Captain Core. Ich habe es nach der Wochentagsberechnung wie das 
auch in Wiki beschrieben ist gemacht. In Wiki habe ich allerdings dafür 
nicht nachgeschaut.

Das mit dem Doomsday blick ich noch nicht. Allein für die Ermittlung 
dieses Tages braucht man ja scho eine Monsterformel.

Autor: Captain Core (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Bernd,
Ich habe nach einem bischen Suchen im Netz auf Seite

(http://lefti.amigager.de/Computer/Java/main.html)

eine recht simple Methode gefunden und in einem kleinen C-Programm ein 
wenig ausgetestet. Ist kein Doomsday, aber es funktioniert scheinbar...
Kannst ja mal probieren.

Grüsse Captain ore

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.