www.mikrocontroller.net

Forum: PC-Programmierung könnte mir jemand kurz über mein C Code schauen ?


Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Servus zusammen,

wäre jemand von euch so nett und schaut kurz über meinen C-Code.
Irgendwas an meinen Berechnungen stimmt nicht.

Es geht um das Julianische Datum - der Algorithmus ist unter 
http://de.wikipedia.org/wiki/Julianisches_Datum#Be... 
dargestellt.

Hier der Auszug:
 wenn Monat > 2 dann  Y = Jahr,   M = Monat
                  sonst Y = Jahr-1, M = Monat+12
   D = Tag 
   H = Stunde/24 + Minute/1440 + Sekunde/86400
    
   wenn TT.MM.YYYY >= 15.10.1582  
        dann Gregorianischer Kalender: A = Int(Y/100), B = 2 - A + Int(A/4)
         
   wenn TT.MM.YYYY <= 04.10.1582  
        dann Julianischer Kalender:                    B = 0
    
   JD = Int(365,25*(Y+4716)) + Int(30,6001*(M+1)) + D + H + B - 1524,5


mich interessiert außschlieslich die Berechnung nach dem 15.10.1582!

Mein Code:
# include <stdio.h>

double JD(int jahr_n, int monat_n, int tag_n, int stunde_n, int minute_n, int sekunde_n);

int main(){
  printf("%lf",JD(2010,3,25,16,30,0));
  getchar();
}

double JD(int jahr_n, int monat_n, int tag_n, int stunde_n, int minute_n, int sekunde_n){
  
  double H=0, A=0, B=0;

  if(monat_n<=2){
    jahr_n--;
    monat_n+=12;
  }

  H=(stunde_n/24)+(minute_n/1440)+(sekunde_n/86400);
  A=((int)(jahr_n/100));
  B=2-A+((int)(A/4));
  return(((int)(365.25*(jahr_n+4716))) + ((int)(30.6001*(monat_n+1))) + tag_n + stunde_n + B - 1524.5);
}


JD(2010,3,25,16,30,0) sollte den 25. März 2010, 16:30:00 Uhr darstellen.

Meine Berechnung gibt aus: 2.455.296,5

Es sollte herauskommen: 2.455.281

Sieht jemand einen Fehler ?

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

Bewertung
0 lesenswert
nicht lesenswert
Lehrmann Michael schrieb:

> Sieht jemand einen Fehler ?

Der Klassiker

  sekunde_n/86400

http://www.mikrocontroller.net/articles/FAQ#Datent...

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

Bewertung
0 lesenswert
nicht lesenswert
JD = Int(365,25*(Y+4716)) + Int(30,6001*(M+1)) + D + H + B - 1524,5

 return(((int)(365.25*(jahr_n+4716))) + ((int)(30.6001*(monat_n+1))) + 
tag_n + stunde_n + B - 1524.5);


In deinem C Code kommt H nicht vor, dafür aber stunde_n

Autor: jl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Der Klassiker
>
>   sekunde_n/86400

Klar ist das H schon mal 0 ist (wenn stunde_n [0..23]). Also richtig 
cast anwenden.

der fehler ist da:
Lehrmann Michael schrieb:
> return(((int)(365.25*(jahr_n+4716))) + ((int)(30.6001*(monat_n+1))) + tag_n + 
stunde_n + B - 1524.5);

aber die Formael sagt:
JD = Int(365,25*(Y+4716)) + Int(30,6001*(M+1)) + D + H + B - 1524,5

ersetze stunde_n durch H und beachte die Anmerkung von Karl heinz

Autor: jl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mist zu langsam :-)

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oha omg. ich Depp und mein Type-Cast ...
Danke an euch beide =)

Klapp leider immernoned

hier mein neuer Code:
# include <stdio.h>

double JD(int jahr_n, int monat_n, int tag_n, int stunde_n, int minute_n, int sekunde_n);

int main(){
  printf("\n%lf",JD(2010,3,25,16,30,0));
  getchar();
}

double JD(int jahr_n, int monat_n, int tag_n, int stunde_n, int minute_n, int sekunde_n){
  
  double H=0, A=0, B=0;

  if(monat_n<=2){
    jahr_n--;
    monat_n+=12;
  }

  H=((double)stunde_n/24)+((double)minute_n/1440)+((double)sekunde_n/86400);
  A=((int)((double)jahr_n/100));
  B=2-A+((int)((double)A/4));
  return(((int)(365.25*((double)jahr_n+4716))) + ((int)(30.6001*((double)monat_n+1))) + (double)tag_n + H + B - (double)1524.5);
}

Bis auf die Nachkommastelle stimmt's jetzt ...

Ich habs bissle übertrieben aber ich find keinen Fehelr mehr !

Autor: didadu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bindet der double stärker an die sekunde oder der /    ?

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
double geht für sekunden_n - aber wenn eines von beiden double ist (in 
diesem fall die sekunden_n dann ist das Ergebnis vom Typ der 
höchstwertige (also double).

H ist auch ein double wenn ich einen printf("%lf",H); mache!

Autor: didadu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Frage ist, ob die der Integer Sekunden ERST durch den 86400 Integer 
geteilt werden (dann ist das Ergebnis IMMER 0) oder ob sie ERST auf den 
double gecastet und DANACH geteilt werden, NUR dann bleibt nämlich von 
den Sekunden ein Wert zwischen 0 und 1 übrig.

Diese Frage betrifft die ganze Kette, die zum H führt.

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
H ist ein double !

0.687500 kommt raus.

Von daher steht es außer Zweifel, dass diese Zeile zumindest im Hinblick 
auf diese Problem korrekt ist. ODER?

Autor: didadu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, dann bindet der cast stärker als die Division.
Das wollte ich wissen.
Danke für die Info.

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: didadu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nee, das, was ich meinte, steht da nicht!

Dein Test hat es für Deinen Programmierfall ergeben und mich aufgeklärt, 
ok.

Aber da Du meinst, dass das da, was ich wissen wollte, da steht, obwohl 
es da nicht steht, solltest Du Dich vielleicht mal allgemein mit der 
Priorität von Operatoren befassen. Also die Frage von Punktrechnung vor 
Strichrechnung, aber ausgedehnt auf alle Operatoren. Da kommt's nämlich 
wirklich auf die Feinheiten an, weil man sonst fiese Fehler übersehen 
könnte.

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

Bewertung
0 lesenswert
nicht lesenswert
Ansonsten kann man immer noch zu Plan B greifen
  H =  stunde_n / 24.0 +
       minute_n / 1440.0 +
       sekunde_n / 86400.0;

Da jetzt die Konstanten mit Sicherheit double sind, bleibt nichts 
anderes übrig als die Divisionen auch als Gleitkommadivisionenen 
auszuführen.
Und übersichtlicher ist es IMHO auch.

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

Bewertung
0 lesenswert
nicht lesenswert
> Bis auf die Nachkommastelle stimmt's jetzt ...

Kannst du das einmal näher beziffern?

Da der Nachkommaanteil im julianischen Datum die Tageszeit kodiert, kann 
eine Angabe von

JD(2010,3,25,16,30,0) sollte den 25. März 2010, 16:30:00 Uhr darstellen.

kein julianisches Datum mit einem Nachkommaanteil von .0 ergeben.

xxx.0 wäre Mittag. Halb 5 Uhr Nachmittags ist ein bischen mehr als ein 
Sechstel Tag. Deine Nachkommastelle müsste also ein wenig größer als 
xxx.1666 sein

(Das ist ganz klar ein Fehler in Wikipedia. Ich hab ihn korrigiert. 
Hätte dir eigentlich auch auffallen müssen :-)

(Und bitte: gewöhn dir den Unsinn mit den Tausenderpunkten wieder ab. 
Die Verwechslungsgefahr mit einem Dezimalpunkt ist einfach viel zu groß! 
Kaufleute brauchen diese Punkte, Techniker benutzen im Zweifelsfall 
Exponenten oder schreiben die Zahl einfach so hin)

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.