C# Geschwindigkeit und Geschwindigkeitsänderung

DasSamu

Newbie
Registriert
Dez. 2017
Beiträge
3
Folgendes Problem bei folgender Übungsaufgabe:
Ein Auto startet zum Zeitpunkt 0 mit der Geschwindigkeit startGeschwindigkeit (positive Ganzzahl in km/h). Alle 30 Minuten erhöht das Fahrzeug die Geschwindigkeit um geschwindigkeitsZuwachs (positive Ganzzahl in km/h). Nach wie vielen Stunden und Minuten (auf zwei Nachkommastellen genau) erreicht das Auto das Ziel in entfernung (positive Ganzzahl in km).
Der Benutzer ist aufzufordern, über die Tastatur die Vorgaben einzugeben.
Das Programm gibt das Ergebnis aus
Und hier drei Testvorgaben: 1.: startGeschwindigkeit: 0, Geschwindigkeitszuwachs: 10 Entfernung: 5 Ankunft: 01:00
2.: startGeschwindigkeit: 0, Geschwindigkeitszuwachs: 1 Entfernung: 5 Ankunft: 02:30
3.: startGeschwindigkeit: 0, Geschwindigkeitszuwachs: 1 Entfernung: 7 Ankunft: 02:54

Mein Lösungsversuch:
Code:
string userInput;
            double startVelocity;
            double changeOfVelocity;
            int distance;
            double minutes=0;
            int hours=0;
            Console.WriteLine("Ziel mit steigender Geschwindigkeit ansteuern");
            Console.WriteLine("=============================================");
            Console.Write("Startgeschwindigkeit: ");
            userInput = Console.ReadLine();
            startVelocity = Convert.ToInt32(userInput);
            Console.Write("Geschwindigkeitszuwachs: ");
            userInput = Console.ReadLine();
            changeOfVelocity = Convert.ToInt32(userInput);
            Console.Write("Entfernung: ");
            userInput = Console.ReadLine();
            distance = Convert.ToInt32(userInput);
            startVelocity /= 60;
            changeOfVelocity /= 60;
           
            while (distance != startVelocity * minutes)
            {
                minutes +=30;
                startVelocity += changeOfVelocity;
            }
            if (minutes >= 60)
            {
                hours = (Int32)minutes / 60;
                minutes %= 60;
            }
            Console.WriteLine();
            Console.WriteLine($"Fahrzeit: {hours} Stunden und {minutes:f} Minuten");
            Console.Write("Programm mit einer beliebigen Taste beenden...");
            Console.ReadKey();

Was genau stimmt nicht, und könnte mir jemand bei der Berechnung generell helfen? Wär super...:p
Sidenote: Ich will NICHT einen Code oder eine Komplettlösung erhalten. Ich kapiere nur überhaupt nicht, wie man das hier berechnet, und ob ich denn auf dem richtigen Weg bin. Das /=60 über der Schleife dient dazu, die km/h in km/min umzurechnen.
 
Zuletzt bearbeitet:
Die While-Schleife ist wohl nicht so ganz richtig. Die Rechnung startVelocity * minutes liefert dir nur die zurückgelegte Distanz für eine konstante Zeit bei einer konstanten Geschwindigkeit. Bei dir ist aber noch eine Beschleunigung dabei.
Am Beispiel 2 heißt es du stehst die ersten 30 Minuten still, fährst die nächsten 30 Minuten mit 1 km/h, nach weiteren 30 min mit 2 km/h etc. Außerdem würdest du bei der dritten Aufgabe scheitern, da du nur 30 Minuten Schritte berücksichtigst. Du musst mit der Genauigkeit auf 1 Minute oder weniger gehen.
 
Zuletzt bearbeitet:
Das erfordert aber wesentlich mehr Rechenleistung, oder? Könnte man nicht einfach die While-Bedingung zu while(distance>velocity*speed) machen?
Dann könnte man doch außerhalb der Schleife eine if-Bedingung machen, welche dann das selbe überprüft und dann eine Rechnung durchführt, in welcher man schaut, wieviele Minuten man noch fahren müsste, um die fehlenden Kilometer zurückzulegen. Das geht mir aber mathematisch nicht auf, wie ich das lösen soll.
 
Warum mehr Rechenleistung? Also an sich ist die While-Schleife keine optimale Lösung, aber dafür anschaulich.
Probier mal die Schleife aber anders aufzubauen:
Code:
//Genauigkeit mit 1 Minute simulieren
int duration = 0;
while(distance > 0) {
  distance = distance - (startVelocity * 1min); // deine angabe in km/min * 1min ergibt die zurückgelegte Distanz in einer Minute
  duration++; // simuliere als ob eine Minute vergangen wäre
  if(duration % 30 == 0)
    startVelocity += changeOfVelocity; // erhöhe die Geschwindigkeit alle 30 Minuten
}
Damit guckst du jede Minute wie viel Strecke du mit der aktuellen Geschwindigkeit zurückgelegt hast bis du die Strecke kleinergleich 0 ist und die duration ist dann die Dauer in Minuten, die du dafür gebraucht hast.
 
Zuletzt bearbeitet:
Aber schlussendlich muss ich doch trotzdem wieder irgendwo eine Rechnung machen, in welcher ich mir eben sowas wie das dritte Beispiel ausrechne- und hier weiß ich nicht, wie ich das weitermache.
 
Man muss nicht unbedingt einen numerischen Ansatz wählen, in dem man die Zeit schrittweise hochzählt.
Es ist einfach, eine geschlossene Formel für die zurückgelegte Distanz nach n * 30 Minuten, n > 0, zu finden.

Da du keine komplette Lösung willst, hier nur ein Paar Ideen.
Die Formel für konstante Geschwindigkeit kennst du ja. x = v * t
In jedem 30 Minuten Abschnitt ist die Geschwindigkeit konstant.
Die geschwindigkeit wird nach jedem Schritt um b erhöht, das heißt die (konstante) Geschwindigkeit in Abschnitt i ist v_i = (v + (i-1) * b)

Für den Zeitschritt der weniger als 30 Minuten dauert, kannst du dann die verbleibende Distanz durch die finale Geschwindigkeit teilen.
 
Da du eigentlich keine Lösung willst, hier nur als Spoiler:

Code:
using System;

namespace Acceleration
{
    class Program
    {
        static void Main(string[] args)
        {
            var startingVelocity = 0;
            var acceleration = 1;
            var delay = 30;
            var distance = 5;

            var result = GetDuration(startingVelocity, acceleration, delay, distance);
            Console.WriteLine(result);
            Console.ReadKey();
        }

        /// <param name="velocity">in km/h</param>
        /// <param name="acceleration">in km/h</param>
        /// <param name="delay">in minutes</param>
        /// <param name="distance">in km</param>
        static double GetDuration(double velocity, double acceleration, double delay, double distance)
        {
            double delayinHours = delay / 60;

            double traveledDistance = 0;
            double traveledTime = 0;

            while (traveledDistance < distance)
            {
                traveledDistance += velocity * delayinHours;
                velocity += acceleration;
                traveledTime += delayinHours;
            }

            double difference = traveledDistance - distance;
            double timeForDifference = difference / velocity;
            double result = traveledTime - timeForDifference;

            return result;
        }
    }
}

Ich glaube, das ist richtig :D

Aber was ich rausgelassen habe, da ich den Zusammenhang nicht finde: Die Ankuftszeit, was sagt sie aus?
 
@Bagbag
Die Ankunftszeit ist das gesuchte Ergebnis, so schwer war der Zusammenhang doch eigentlich nicht zu erkennen? ;)
 
DasSamu schrieb:
Aber schlussendlich muss ich doch trotzdem wieder irgendwo eine Rechnung machen, in welcher ich mir eben sowas wie das dritte Beispiel ausrechne- und hier weiß ich nicht, wie ich das weitermache.

Wegen dem dritten Beispiel musst du ja gerade Minutengenau rechnen, was in meinen Vorschlag auch berücksichtigt wird. Die duration ist das Ergebnis in Minuten, was du noch in Stunden:Minuten umrechnen musst, was du bereits richtig gemacht hast.
 
Zuletzt bearbeitet:
simpsonsfan schrieb:
@Bagbag
Die Ankunftszeit ist das gesuchte Ergebnis, so schwer war der Zusammenhang doch eigentlich nicht zu erkennen? ;)

:freak: aso, das ist das Ergebnis zum gegenprüfen. Ich dachte erst das sei irgendwie ein Parameter. Dann funktioniert der Code, mit der Ausnahme, das beim 3. 2:55 statt 2:54 rauskommt ?!

Hier nochmal mit verbesserter Ausgabe:
Code:
using System;

namespace Acceleration
{
    class Program
    {
        static void Main(string[] args)
        {
            var result1 = GetDuration(0, 10, 30, 5);
            var result2 = GetDuration(0, 1, 30, 5);
            var result3 = GetDuration(0, 1, 30, 7);

            PrintResults(result1, result2, result3);

            Console.ReadKey();
        }

        private static void PrintResults(params TimeSpan[] results)
        {
            foreach (var result in results)
            {
                var formatted = Format(result);
                Console.WriteLine(formatted);
            }
        }

        private static string Format(TimeSpan timeSpan)
        {
            var hours = timeSpan.Hours.ToString("00");
            var minutes = timeSpan.Minutes.ToString("00");

            return $"{hours}:{minutes}";
        }

        /// <param name="velocity">in km/h</param>
        /// <param name="acceleration">in km/h</param>
        /// <param name="delay">in minutes</param>
        /// <param name="distance">in km</param>
        /// <returns>minutes</returns>
        static TimeSpan GetDuration(double velocity, double acceleration, double delay, double distance)
        {
            double delayinHours = delay / 60;

            double traveledDistance = 0;
            double traveledTime = 0;

            while (traveledDistance < distance)
            {
                traveledDistance += velocity * delayinHours;
                velocity += acceleration;
                traveledTime += delayinHours;
            }

            double difference = traveledDistance - distance;
            double timeForDifference = difference / velocity;
            double result = traveledTime - timeForDifference;

            return TimeSpan.FromHours(result);
        }
    }
}

@distrophik

Da jede Minute zu iterieren ist unnötig, ungenauer und langsamer. Mit etwas Mathe bekommt man es ganz genau und es ist pro Beschnleunigung nur eine Rechnung.
 
Zuletzt bearbeitet:
@Bagbag
Das ist schon klar, es geht auch ohne While-Schleife und alles nur in einer Zeile. Ich wollte nur deutlich machen was genau passiert und was in der Anfangslösung nicht berücksichtigt wurde.
 
Naja, die zurückgelegte Strecke s(t) lässt sich analytisch hinschreiben. Allerdings enthält dieser Ausdruck dann eine Summe. Somit muss man, um es nach t aufzulösen sowieso irgendwo eine Schleife verwenden.

Jedenfalls ist es bei so einem kleinen Problem nun auch nicht unbedingt sinnvoll, Flops/Instructions zu zählen, dafür ist der Gesamtaufwand schlicht zu gering.

Und @Bagbag, dass bei dir 2:55 statt 2:54 rauskommt ist übrigens ein Bug, da hast du noch einen kleinen Fehler im Algorithmus, es kommt nämlich im dritten Testfall exakt 2,9 h raus. Ist aber schnell angepasst, so dass es stimmt.
 
@simpsonsfan, magst du mir auf die Sprünge helfen?
 
Wenn du so fragst... typischer off-by-1-Fehler. Die Geschwindigkeit wird für den Differenzteil einmal zu viel erhöht bzw. muss wieder einmal reduziert werden.
 
Zurück
Oben