2010-11-21 38 views
6

Cố gắng mô phỏng rollover của đồng hồ 24 giờ bằng tay (với toán học so với sử dụng các lớp thời gian). Phần gia tăng là dễ dàng để tìm ra cách để cuộn từ 23:00 đến 0:00 và từ, nhưng làm cho nó đi theo cách khác là hóa ra là thực sự khó hiểu. Dưới đây là những gì tôi có cho đến thời điểm này:C#: giảm một đồng hồ bằng cách sử dụng phép toán modulus

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); 
} 

Vấn đề mà việc tìm kiếm là khi quay ngược lại, nếu mô đun nằm giữa các số, nó sẽ không giảm một cách chính xác. Ví dụ: 12:00 và bạn trừ đi 61 phút, chúng tôi biết thời gian là 10:59 vì giờ sẽ quay lại 1 giờ để đi từ 12:00 đến 11:59, sau đó quay lại để đi từ 11:00 đến 10:59. Thật không may là cách tính toán nó: newMin% 60 trong trường hợp này, chỉ lấy rollback giờ đầu tiên, nhưng kể từ khi rollback thứ hai là kỹ thuật -1.0166 như phần còn lại, và vì mod chỉ trả về một số nguyên, làm tròn nó đi. Im chắc chắn im thiếu một số toán học cơ bản ở đây, nhưng ai đó có thể giúp tôi ra?

EDIT: Tôi đã viết một số cách dài và ngắn. Một số thì gần hơn những người khác, nhưng tôi biết điều này đơn giản hơn vẻ bề ngoài. Tôi biết điều này dường như là một "wtf anh ấy đang làm", nhưng bạn sẽ có thể nhìn thấy cơ bản những gì Im đang cố gắng làm. Tăng thêm một chiếc đồng hồ và việc di chuyển nó từ 23:59 đến 0:00 thật dễ dàng. Đi ngược lại đã được chứng minh là không dễ dàng như vậy.

OK, đây là giá trị gia tăngThay đổi với rollover. Đơn giản. Nhưng hãy cố lùi lại. Không hoạt động.

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); 
     } 
+1

bạn có thể thêm một chút chi tiết này, đặc biệt là một ví dụ sử dụng và nhà nước dự kiến ​​của biến toàn cầu? – steinar

+0

Giá trị nào 'min' và' incr' có? – ChrisF

+0

Tôi tin rằng tôi đã đưa ra những ví dụ đó. Về cơ bản, làm thế nào để tôi mã decrement để có 12:00 - 0:61 = 10:59 và có nó làm việc cho gia số là tốt. – Sinaesthetic

Trả lời

1

tôi muốn đi cho một cái gì đó đơn giản hơn một chút

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); 
    } 
} 

Sử dụng mẫu:

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 
+0

Trong chức năng AddMinutes của bạn: s/if/while /, trong trường hợp người dùng thêm số phút âm trong một ngày. – jtdubs

+0

@jtdubs, 'this.totalMinutes% = MinutesPerDay;' quan tâm đến điều đó;) – Diadistis

+0

@Sinh tế, nếu bạn định sử dụng lớp này, hãy nhớ rằng nó không phải là chủ đề an toàn. – Diadistis

0

Toán học mô-đun chỉ được xác định cho số nguyên. Nếu bạn đang cố gắng để trộn lẫn số học mô-đun với số thực bạn sẽ không thành công. Bạn cần tìm ra cách tiếp cận toán học khác.

+0

việc truyền số thực chỉ là nhập cấu trúc điều khiển. Tôi đã cố gắng để đảm bảo rằng nó sẽ trừ ít nhất 1 giờ, nhưng tôi phát hiện ra rằng nó sẽ gây ra vấn đề với giảm tiếp theo nếu nó ít hơn 1 giờ đầy đủ. gây nhầm lẫn ... – Sinaesthetic

+0

có, nhưng về mặt khái niệm bạn muốn phần còn lại. Nó sẽ không xảy ra bằng cách sử dụng số học mô-đun trừ khi bạn tách biệt giờ và phút trước khi áp dụng mô-đun. – joejoeson

+0

số giờ và phút được tách ra trước khi áp dụng mô đun. – Sinaesthetic

1

Bạn có thể thử tính cả increments phút và giờ đầu tiên, sau đó xử lý trường hợp phút mới vượt qua một ranh giới giờ, một cái gì đó như thế này:

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++; 
} 

Sửa

Tôi thích @Ben Voigts câu trả lời, nhưng đã tự hỏi nếu có bất kỳ sự khác biệt nào về hiệu suất. Tôi chạy ứng dụng giao diện điều khiển dưới đây để thời gian cả hai, và đã được một chút ngạc nhiên bởi kết quả.

  • 40 ms cho mã trên
  • 2876 ms cho câu trả lời của Ben

này được thực hiện trong một thông cáo xây dựng. Bất cứ ai khác có thể chạy điều này và xác nhận? Tôi có mắc sai lầm gì trong cách tôi thời gian không?

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; 
     } 
    } 
} 
+0

ở cái nhìn đầu tiên, điều này sẽ không hoạt động nếu bạn đã đi hơn một giờ về phía sau. Đây là loại mà tôi đã được khoảng một giờ trước đây: ( – Sinaesthetic

+0

@ Thẩm mỹ, có lẽ tôi là sự hiểu lầm, nhưng nếu tôi bắt đầu với 'min == 0' và' incr = -121', tôi nhận được 'newMin == 59 ', và' hourIncrement == -3'. Điều đó có đúng không? –

+0

@adrift: Dường như với tôi như nó sẽ hoạt động, nhưng nó phức tạp hơn mức cần thiết –

0

Hãy thử

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

     min -= hourIncrement * 60; 

Vấn đề quan trọng là bạn muốn hourIncrement làm tròn xuống, nhưng vòng phân chia số nguyên đối với zero. Chúng giống nhau với số dương, nhưng không phải là số âm ...

EDIT (loại bỏ biến thêm vô dụng):

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

EDIT2 (tránh dấu chấm động số học):

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

ok Math.Floor là những gì tôi đang tìm kiếm. Không giải quyết được sự hồi phục phút, nhưng nó có phần mà tôi đã đấu tranh nhiều nhất. Tôi nghĩ tôi có thể lấy nó từ đây nhờ. – Sinaesthetic

+0

Tôi đã cung cấp mã để xử lý thời gian chờ, nhưng đã bị lẫn lộn bởi thực tế bạn không thực sự đặt phút mới trong 'newMin'. Xem http: // ideone.com/i3Yom –

0

Tại sao đến những điều phức tạp

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) 
    } 
Các vấn đề liên quan