C#: انخفاض ساعة باستخدام Modulus Math
سؤال
في محاولة لمحاكاة نقل الساعة على مدار 24 ساعة باليد (مع الرياضيات مقابل استخدام فصول الزمنية). كان من السهل معرفة الجزء المتزايد من كيفية التدحرج من الساعة 23:00 إلى 0:00 ومن ، لكن الحصول عليه في الاتجاه الآخر هو أمر محير حقًا. هذا ما لدي حتى الآن:
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);
}
المشكلة التي تجدها هي عند العودة إلى الوراء ، إذا كانت معامل معامل الأرقام بين الأرقام ، فلن تنخفض بشكل صحيح. مثال: إنه الساعة 12:00 وطرح 61 دقيقة ، نعلم أن الوقت سيكون 10:59 حيث يجب أن تتدحرج الساعة 1 ساعة للذهاب من الساعة 12:00 إلى 11:59 ، ثم العودة مرة أخرى للذهاب من الساعة 11:00 إلى 10:59. لسوء الحظ ، فإن الطريقة التي أحسب بها: Newmin ٪ 60 في هذه الحالة ، لا تحصل إلا على التراجع عن الساعة الأولى ، ولكن نظرًا لأن التراجع الثاني هو من الناحية الفنية -1.0166 كباقي ، وبما أن MOD لا يعيد سوى عدد كامل ، فإنه يدور حوله. أنا متأكد من أنني أفتقد بعض الرياضيات الأساسية هنا ، لكن هل يمكن لأي شخص مساعدتي؟
تحرير: لقد كتبت هذا عدة طرق طويلة وقصيرة. البعض أقرب من الآخرين ، لكنني أعلم أن هذا أبسط مما يبدو. أعلم أن هذا يبدو "wtf كان يفعله" ، لكن يجب أن تكون قادرًا على رؤية ما أحاول القيام به بشكل أساسي. من السهل زيادة الساعة وإنشاءها من 23:59 إلى 0:00. لقد أثبتت العودة إلى الوراء أنها ليست سهلة.
حسنًا ، ها هي الإزداد مع التمديد. بسيط. لكن حاول العودة إلى الوراء. لا يعمل.
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);
}
المحلول
سأذهب لشيء أكثر بساطة
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);
}
}
استخدام العينة:
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
نصائح أخرى
قد تحاول حساب الزيادات الدقيقة والساعة أولاً ، ثم التعامل مع الحالات التي تعبر فيها الدقائق الجديدة حدود ساعة ، شيء من هذا القبيل:
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++;
}
تعديل
أحب إجابة ben voigts ، لكنني كنت أتساءل عما إذا كان هناك أي فرق في الأداء. قمت بتشغيل تطبيق وحدة التحكم أدناه إلى وقتهم ، وفوجئت قليلاً بالنتائج.
- 40 مللي ثانية للرمز أعلاه
- 2876 مللي ثانية لإجابة بن
وقد تم ذلك في بناء الإصدار. هل يمكن لأي شخص آخر تشغيل هذا وتأكيد؟ هل أرتكب أي أخطاء في الطريقة التي أتيت بها؟
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;
}
}
}
يتم تعريف الرياضيات المعيارية فقط للأعداد الصحيحة. إذا كنت تحاول خلط الحساب المعياري بأرقام حقيقية ، فلن تنجح. تحتاج إلى معرفة نهج رياضي مختلف.
محاولة
int newMin = min + incr,
hourIncrement = (int)Math.Floor(newMin / 60.0);
min -= hourIncrement * 60;
كانت المشكلة الأساسية التي تريدها hourIncrement
لتجول لأسفل ، ولكن تقسيم عدد صحيح نحو الصفر. إنها نفسها مع الأرقام الإيجابية ، ولكن ليس للسلبية ...
تحرير (التخلص من متغير إضافي غير مجدي):
min += incr;
int hourIncrement = (int)Math.Floor(min / 60.0);
min -= hourIncrement * 60;
EDIT2 (تجنب الحساب العائم):
min += incr;
int hourIncrement = min / 60;
min -= hourIncrement * 60;
if (min < 0) { min += 60; --hourIncrement; }
لماذا تعقد الأشياء
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)
}