Pregunta

Tratando de emular el vuelco de un reloj de 24 horas con la mano (con vs. matemáticas utilizando las clases TimeSpan). La parte de incremento era fácil de encontrar la manera de rodar encima de 23:00 a 0:00 y desde, pero conseguir que se vaya a otro lado está resultando ser realmente confuso. Esto es lo que tengo hasta ahora:

static void IncrementMinute(int min, int incr)
{
    int newMin = min + incr,
                hourIncrement = newMin / 60;

    //increment or decrement the hour
    if((double)newMin % 60 < 0 && (double)newMin % 60 > -1)
        hourIncrement = -1;

    Console.WriteLine("Hour increment is {0}: ", hourIncrement);
}

El problema que im hallazgo es cuando va hacia atrás, si el módulo de es entre los números, no va a disminuir correctamente. Ejemplo: es 12:00 y se resta 61 minutos, sabemos que el tiempo sería la hora 10:59 como debe deshacerse de 1 hora para ir 12:00-11:59, a continuación, volver de nuevo para ir desde las 11:00 a 10:59. Por desgracia la forma im calcularlo: newMin% 60 en este caso, sólo agarra la primera reversión horas, pero desde la segunda reversión es técnicamente -1.0166 como un resto, y desde mod sólo devuelve un número entero, su redondeo. Estoy seguro de im falta un poco de matemática básica aquí, pero es posible que alguien me ayude?

EDIT: He escrito esto varias formas larga y corta. Algunos son más cercanos que otros, pero sé que esto es más sencillo de lo que parece. Sé que éste parece un poco "wtf estaba haciendo", pero debería ser capaz de ver, básicamente, lo que estoy tratando de hacer. Incremento de un reloj y hacer que vuelco de 23:59 a 0:00 es fácil. Yendo hacia atrás ha demostrado no ser tan fácil.

OK, aquí está la incrementMinute con el vuelco del vehículo. Sencillo. Pero tratar de ir hacia atrás. No funciona.

static void IncrementMinute(int min, int incr)

        {
            int newMin = min + incr,
                hourIncrement = newMin / 60;

            min = newMin % 60;

            Console.WriteLine("The new minute is {0} and the hour has incremented by {1}", min, hourIncrement);
        }
¿Fue útil?

Solución

Me gustaría ir por algo un poco más simple

public class Clock
{
    public const int HourPerDay = 24;
    public const int MinutesPerHour = 60;
    public const int MinutesPerDay = MinutesPerHour * HourPerDay;

    private int totalMinutes;

    public int Minute
    {
        get { return this.totalMinutes % MinutesPerHour; }
    }

    public int Hour
    {
        get { return this.totalMinutes / MinutesPerHour; }
    }

    public void AddMinutes(int minutes)
    {
        this.totalMinutes += minutes;
        this.totalMinutes %= MinutesPerDay;
        if (this.totalMinutes < 0)
            this.totalMinutes += MinutesPerDay;
    }

    public void AddHours(int hours)
    {
        this.AddMinutes(hours * MinutesPerHour);
    }

    public override string ToString()
    {
        return string.Format("{0:00}:{1:00}", this.Hour, this.Minute);
    }
}

Ejemplo de uso:

new Clock().AddMinutes(-1);    // 23:59
new Clock().AddMinutes(-61);   // 22:59
new Clock().AddMinutes(-1441); // 23:59
new Clock().AddMinutes(1);     // 00:01
new Clock().AddMinutes(61);    // 01:01
new Clock().AddMinutes(1441);  // 00:01

Otros consejos

Usted puede tratar de calcular los dos incrementos de un minuto y la hora en primer lugar, a continuación, el manejo de casos en los que las nuevas minutos cruza una frontera hora, algo como esto:

int hourIncrement = incr / 60;
int minIncrement = incr % 60;

int newMin = min + minIncrement;

if (newMin < 0)
{
    newMin += 60;
    hourIncrement--;
}
else if (newMin > 60)
{
    newMin -= 60;
    hourIncrement++;
}

Editar

I como respuesta @Ben Voigts, pero me preguntaba si no habría ninguna diferencia en el rendimiento. Me encontré con la aplicación de consola a continuación en cuando a los dos, y estaba un poco sorprendido por los resultados.

  • 40 ms para el código de seguridad
  • 2876 ms para la respuesta de Ben

Esto se hizo en una versión de lanzamiento. ¿Alguien más puede funcionar esto y confirmar? Am cometer errores en el tiempo como yo las he?

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();

            int max = 100000000;

            sw.Start();
            for (int i = 0; i < max; i++)
                IncrementMinute1(0, -61);
            sw.Stop();

            Console.WriteLine("IncrementMinute1: {0} ms", sw.ElapsedMilliseconds);

            sw.Reset();

            sw.Start();
            for (int i = 0; i < max; i++)
                IncrementMinute2(0, -61);
            sw.Stop();

            Console.WriteLine("IncrementMinute2: {0} ms", sw.ElapsedMilliseconds);

            Console.ReadLine();
        }

        static void IncrementMinute1(int min, int incr)
        {
            int hourIncrement = incr / 60;
            int minIncrement = incr % 60;

            int newMin = min + minIncrement;

            if (newMin < 0)
            {
                newMin += 60;
                hourIncrement--;
            }
            else if (newMin > 60)
            {
                newMin -= 60;
                hourIncrement++;
            }
        }

        static void IncrementMinute2(int min, int incr)
        {
            min += incr;
            int hourIncrement = (int)Math.Floor(min / 60.0);
            min -= hourIncrement * 60;
        }
    }
}

matemáticas modulares sólo se define por los números enteros. Si está intentando mezclar la aritmética modular con números reales que no tendrá éxito. Es necesario encontrar una aproximación matemática diferente.

Trate

        int newMin = min + incr,
            hourIncrement = (int)Math.Floor(newMin / 60.0);

        min -= hourIncrement * 60;

El problema esencial es que desea hourIncrement a abajo todo el año, pero rondas división entera hacia cero. Son lo mismo con números positivos, pero no para el negativo ...

Edit (para deshacerse de inútil variables extra):

    min += incr;
    int hourIncrement = (int)Math.Floor(min / 60.0);
    min -= hourIncrement * 60;

Edit2 (Evitar aritmética de punto flotante):

    min += incr;
    int hourIncrement = min / 60;
    min -= hourIncrement * 60;
    if (min < 0) { min += 60; --hourIncrement; }

¿Por qué complicar las cosas

public System.Timers.Timer timer = new System.Timers.Timer(1000);
public DateTime d;

public void init()
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);

d = new DateTime(2011, 11, 11, 23, 59, 50);
d=d.AddHours(1);
Console.Writeline(d);
d=d.AddHours(-2);
Console.Writeline(d);
timer.Enabled = true;
}
   void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
        {
            MoveClockHands();
            d=d.AddSeconds(1);
            Console.WriteLine(d);

        }));
    }

    void MoveClockHands()  //12 hours clock
    (
       s=d.Second * 6;
       m=d.Minute * 6;
       h=0.5 * ((d.Hour % 12) * 60 + d.Minute)
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top