Entwickler-Ecke

C# - Die Sprache - Rechnungsprobleme mit Datentyp "double"


Kirk1701A - Mi 26.09.18 05:42
Titel: Rechnungsprobleme mit Datentyp "double"
Jolan Tru,

ich programmiere gerade eine Klassenbibliothek (soll später als nuget veröffentlicht werden), die Sternzeiten nach StarTrek TOS und TNG berechnen kann. Dazu brauche ich natürlich die Informationen des jeweiligen Datums.

Das Problem besteht darin, dass ich die Stunde des Tages durch 24 teilen muss und die Minute der Stunde durch 1440 teilen muss. Das muss ich komplett aufsplitten (die gesamte Rechnung meine ich damit), damit ein richtiges Ergebnis erreicht werden kann.

D.H.

C#-Quelltext
1:
2:
double foo = Convert.ToDouble(DateTime.Now.Hour / 24);
double foobar = Convert.ToDouble(DateTime.Now.Minute / 1440);


Wenn man beim Debugging über das '/' hovert, kommt im Context das richtige Kommaergebnis.

Das ist ja alles gut und schön, nur, dieses Ergebnis wird nie und nimmer den Variablen (foo und foobar) zugewiesen. Das verstehe ich einfach nicht. :gruebel: :autsch: :motz:

Danke für eure Hilfe

LLAP
Euer Kirk



P.S.
Ich habe schon so ziemlich alle Convertierungsmethodiken benutzt, aber keine hat geklappt.


Christian S. - Mi 26.09.18 09:06

Die Minute-Eigenschaft eines DateTime hat einen Wert zwischen 0 und 59. Wenn Du das durch 1440 teilst, ist das, weil es eine Integer-Division ist, immer Null.


Th69 - Mi 26.09.18 09:07

Da du jeweils zwei Ganzzahlen dividierst, kommt als Ergebnis auch eine Ganzzahl heraus und diese Zahl wird dann erst in eine Fließkommazahl verwandelt.

Du brauchst auch die Convert-Methode nicht, es reicht, wenn eine der beiden Zahlen eine Fließkommazahl ist:

C#-Quelltext
1:
2:
double foo = DateTime.Now.Hour / 24.0;
double foobar = DateTime.Now.Minute / 1440.0;


PS: Der Debugger (das Watch-Fenster bzw. Tooltip) benutzt bei Rechnungen stets Fließkommazahlen, da er die konkreten Datentypen nicht heranzieht.


Kirk1701A - Mi 26.09.18 20:18

Jolan Tru,

danke für eure Hilfe.

Leider hat das alles auch nicht funktioniert. Entweder erscheint kein Tooltip oder es wird (bei meiner aktuellen Rechnung (20/24=0,86666666666666666666666666666666...)) -304,257888... zugewiesen. Also ein total falsches Ergebnis.

Hinzu kommt, dass das Debugging einer Klassenbibliothek (natürlich mit angeschlossener Konsole) die totale Hölle ist.

Entweder will mein VS mich ärgern, oder ich bin unfähig meinen Beruf auszuüben, oder ich habe einen Fehler gemacht, den ich absolut nicht erkenne. Unter diesem Abschnitt seht Ihr die gesamte Methode, in der die Rechnung durchgeführt wird.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
/// <summary>
        /// Calculates the TNG (The Next Generation) stardate
        /// </summary>
        /// <param name="useCurrentDate">The choose if this method have to use the current Date</param>
        /// <returns>complete Stardate</returns>
        private static double CalcTNGStardate(bool useCurrentDate)
        {
            double Stardate;
            double dayOfYear = DateTime.Now.DayOfYear;
            double hourOfDay = DateTime.Now.Hour;
            double minuteOfHour = DateTime.Now.Minute;

            //Checks the given date and calculate the Stardate
            if (!useCurrentDate)
            {
                bool isLeapYear = CheckLeapYear(Year);

                if (isLeapYear)
                {
                    dayOfYear = DayOfMonth + (153 * Month - 157) / 5;
                    Stardate = 1000 * (Year + 1 / 366 * (dayOfYear - 1 + HourOfDay / 24 + MinuteOfHour / 1440) - 2323);
                }
                else
                {
                    dayOfYear = DayOfMonth + (153 * Month - 162) / 5;
                    Stardate = 1000 * (Year + 1 / 365 * (dayOfYear - 1 + HourOfDay / 24 + MinuteOfHour / 1440) - 2323);
                }
            }
            else
            {
                Year = DateTime.Now.Year;
                bool isLeapYear = CheckLeapYear(Year);

                if (isLeapYear)
                {
                    Stardate = dayOfYear - 1 + (HourOfDay / 24) + (MinuteOfHour / 1440);
                    Stardate = 366 * Stardate;
                    Stardate = Year + (1 / Stardate);
                    Stardate = (1000 * Stardate) - 2323;

                    //Stardate = 1000 * (Year + 1 / 365 * (dayOfYear - 1 + HourOfDay / 24 + MinuteOfHour / 1440) - 2323);
                }
                else
                {
                    double foo = DateTime.Now.Hour / 24.0;

                    minuteOfHour = minuteOfHour / 1440.0;

                    Stardate = dayOfYear - 1 + hourOfDay + minuteOfHour;
                    double booh = 365.0 * Stardate;
                    Stardate = Year + 1.0 / booh - 2323.0;
                    Stardate = 1000.0 * Stardate;

                    Console.WriteLine(Year);
                }
            }

            return Stardate;
        }


Ich danke euch jetzt schon für den moralischen Ar***tritt...

LLAP
Euer Kirk


Christian S. - Mi 26.09.18 20:48

Hallo,

der Quelltext in der Form nutzt wahrscheinlich nicht viel, weil wir ja nicht so firm darin sind, die Sternzeit zu berechnen ;)

Breche doch mal die problematischen Stellen in einfache, isolierte Rechnungen runter, bei denen man dann gucken kann, warum nicht das erwartete Ergebnis heraus kommt. Wichtig ist dabei immer, dass (1) ein überschaubarer Quelltext, (2) das erwartete Ergebnis und (3) das tatsächlich errechnete Ergebnis klar sind.

Grüße
Christian


Kirk1701A - Do 27.09.18 05:57


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
else
{
    double foo = DateTime.Now.Hour / 24.0;

    minuteOfHour = minuteOfHour / 1440.0;

    Stardate = dayOfYear - 1 + hourOfDay + minuteOfHour;
    double booh = 365.0 * Stardate;
    Stardate = Year + 1.0 / booh - 2323.0;
    Stardate = 1000.0 * Stardate;

    Console.WriteLine(Stardate);
}


Jolan Tru,

sorry, aber der jetzt hier gezeigte Ausschnitt hat genau das gemacht (Rechnungen gesplittet, usw.). Es geht mir hauptsächlich um die Variable 'foo', da diese ein total falsches Ergebnis errechnet bekommt:

C#-Quelltext
1:
double foo = DateTime.Now.Hour / 24.0;                    


Hier kommt eine 3-stellige, negative Kommazahl mit mind. 12 Nachkommastellen. Das ist falsch.

LLAP
Euer Kirk


jasocul - Do 27.09.18 07:24

Prüfst du das nur im Debugger oder lässt du dir den Wert in der Konsole anzeigen?
Mal abgesehen davon ist 20/24 = 0,8333.. :wink:

Wenn du das nur im Debugger ansiehst, solltest du dir foo und evtl. Hour mal in der Konsole anzeigen lassen.
C# ist bei mir schon eine ganze Zeit her, aber vielleicht wird dort optimiert und eine Variable, die im folgenden Source nicht genutzt wird, enthält dann keine sinnvollen Daten, da es wegoptimiert wurde.


Palladin007 - Do 27.09.18 08:41

@jasocul:
Im Debug-Modus optimiert der Compiler nicht - sollte er zumindest nicht, das kann man einstellen.

@Kirk1701A:
jasocul hat ja schon geschrieben, dass die 0,866666666666666 (Edit: 0,833333333333333) das richtige Ergebnis sind, es ist eben Periode 6 3.
Wenn Du nur 0,86 0,83 haben willst, musst Du das selber erreichen, z.B. indem Du mit 100 multiplizierst und dann nach int castest.

Moderiert von user profile iconTh69: Auch die anderen Schreibfehler überarbeitet.


Th69 - Do 27.09.18 10:10

Palladin007: Hast du dich von Kirk anstecken lassen? :D

20 / 24 = 0,8333...


Palladin007 - Do 27.09.18 14:02

... Verdammt :D
Ich hab's selber nochmal nachgerechnet und dann falsch abgeschrieben
Typisch Montag an einem Donnerstag :D

Danke für die Korrektur


Kirk1701A - Do 04.10.18 11:44

Hallo Leute,

ich habe das Problem nun gelöst. Es funktioniert fabelhaft; Dankeschön.

Die Klasse ist nun als Nuget unter dem Namen "StarDateCalc" zum freien Download verfügbar. Besitzt keinerlei Abhängigkeiten und ist die genaueste Sternzeitberechnung für TOS und TNG, die jemals veröffentlicht wurde.

LLAP
Euer Kirk