خوارزمية لتحديد ما إذا كان معطى / التاريخ الآن هو بين اثنين من تاريخ زوجا / الساعة

StackOverflow https://stackoverflow.com/questions/637505

سؤال

ولدي مجموعة من التواريخ في نطاق أسبوع واحد المخزنة بطريقة غير معتادة.

ويتم تخزين التواريخ في هذه تنسيق رقمي: 12150

ومن اليسار إلى اليمين:

ويمثل الرقم 1ST اليوم: 1 = الأحد، 2 = الاثنين، 3 = الثلاثاء، ....، 7 = السبت

وبعد ذلك تمثل رقمين ساعة في نظام 24 ساعة: 00 = منتصف الليل، 23 = 11:00

وبعد ذلك رقمين تمثل دقائق: 00-59

ونظرا لتاريخ الإدخال وتاريخ بداية ونهاية التاريخ أريد أن أعرف إذا كان تاريخ الإدخال بين بداية ونهاية التاريخ.

ولدي خوارزمية الآن بأنني <م> التفكير يعمل 100٪ من الوقت، لكنني لست متأكدا.

في أي حال، أعتقد أن هناك من المحتمل ان يكون طريقة أفضل وأبسط للقيام بذلك، وأنا أتساءل عما اذا كان يعرف أي شخص ما كان أن الخوارزمية.

إذا لم أنه سيكون باردا إذا كان شخص ما يمكن أن يتضاعف تحقق عملي والتحقق من أنه يعمل فعلا ل100٪ من الحالات صالحة.

ما لدي الآن هو:

if (startDate < inputDate && 
    endDate > inputDate) {
        inRange = yes;    
}
else if (endDate < startDate) {
        if((inputDate + 72359) > startDate &&
          (inputDate + 72359) < endDate) {
          inRange = yes; 
        }
        else if((inputDate + 72359) > startDate &&
               (inputDate + 72359) < (endDate + 72359)) {
          inRange = yes;   
        }

}
هل كانت مفيدة؟

المحلول

وماذا عن

const int MAX = 72460; // Or anything more than the highest legal value
inRange = (MAX + inputDate - startDate) % MAX < 
          (MAX + endDate - startDate) % MAX;

وهذا يفترض بالطبع أن كل التواريخ ومنسق بشكل جيد (وفقا لمواصفات الخاصة بك).

وهذا يتناول الحالة التي يكون فيها كانت البداية "بعد كلمة" النهاية. (على سبيل المثال يوم الجمعة هو في نطاق لو بداية غير الاربعاء ونهاية هو يوم الاثنين)

وقد يستغرق ثانية لرؤية (الذي هو على الارجح ليست جيدة، لأن القراءة هي عادة ما تكون أكثر أهمية) ولكن أعتقد أنه لا عمل.

وهنا الخدعة الأساسية:

Legend: 

  0: Minimum time
  M: Maximum time

  S: Start time
  1,2,3: Input Time test points
  E: End Time

The S  E => Not in range
  2  In range
  3 > E => Not in range

The S > E case
                        0                 M
  Original              -1--E----2---S--3--
  Add Max               -------------------1--E----2---S--3--
  Subtract StartDate    ------1--E----2---S--3--      
  % Max                 S--3--1--E----2----

  1  In range
  2 > E => Not in range
  3  In range

إذا كنت حقا تريد أن تذهب المكسرات (ويكون أكثر صعوبة في فك)

const int MAX = 0x20000; 
const int MASK = 0x1FFFF;
int maxMinusStart = MAX - startDate;
inRange = (maxMinusStart + inputDate) & MASK < 
          (maxMinusStart + endDate) & MASK;

والذي يجب أن يكون أسرع قليلا (معامل التداول لأحادي المعامل و) الذي يمكننا القيام به منذ قيمة MAX لا يهم حقا (طالما أنه يتجاوز الحد الأقصى للقيمة بشكل جيد) ونحن أحرار في اختيار واحد التي تجعل الحسابات لدينا سهلة.

(وبالطبع يمكنك استبدال < مع <= إذا كان هذا هو ما تحتاجه حقا)

نصائح أخرى

وهناك بعض خطأ منطقي مع تواريخ في هذا الشكل. لأن المعلومات الشهر والسنة مفقود، لا يمكنك معرفة أي يوم تقويم مفقود. مثلا قد يكون 50755 الخميس 12 مارس 2009، لكنه قد يكون مجرد كذلك قبل أسبوع بالضبط، أو 18 الأسابيع المقبلة. ذلك لك لا يمكن أبدا أن يكون متأكدا 100٪ إذا <م> أي التاريخ في هذا الشكل هو ما بين <م> أي 2 تواريخ أخرى.

وهنا حالة من if الداخلية لا يمكن أبدا أن يكون صحيحا، منذ endDate < startDate:

if (endDate < startDate) {
  if((inputDate + 72359) > startDate &&
    (inputDate + 72359) < endDate) {
    // never reached
    inRange = yes; 
  }

وفيما يلي إذا أيضا لا يمكن أن يكون الأمثل، منذ الجزء الأول هو دائما صحيح، والجزء الثاني هو مجرد مطابقة لinputDate < endDate:

  if((inputDate + 72359) > startDate &&
     (inputDate + 72359) < (endDate + 72359))

وأعتقد أنك تريد شيئا من هذا القبيل:

if (startDate < endDate)
  inRange = (startDate < inputDate) && (inputDate < endDate);
else
  inRange = (startDate < inputDate) || (inputDate < endDate);

ويجب عليك استخدام => و <= إذا كنت تريد ذلك حقا في النطاق

وأقول إنني اختيار هذا التاريخ 10000 أو 72359، وكيف سيكون التعامل مع هذا؟ هو في نطاق أم لا؟

وأيضا لم أكن أعرف قيمة لتاريخ البدء وENDDATE منذ كنت لم تهيئة ذلك، تصحيح لي إذا كنت مخطئا، المتغير الذي لم تهيئة ستبدأ مع 0 أو خالية أو ''

ولذا فإنني تحمل تاريخ البدء = 10000 وENDDATE 72359

وبالمناسبة لماذا اخترت هذا النوع من مجموعة (ك int أو قيمة السلسلة؟) لماذا لأول مرة قيمة كان يوم؟ لا تاريخ المثال:
010000 -> تاريخ 1 شهر 00:00 في
312359 -> تاريخ 31th من الشهر 23:59

ولكن الامر متروك لك: D

وآسف حتى لو كنت على خطأ أخذت الطبقة الخوارزمية فقط على الجامعة وكان قبل 5 سنوات: D

قد يكون طريقة أفضل لتطبيع البيانات تحويل كل يوم من أيام الأسبوع القيم لتكون نسبة إلى تاريخ البدء. شيء من هذا القبيل:

const int dayScale = 10000;  // scale factor for the day of the week

int NormalizeDate(int date, int startDay) 
{
    int day = (date / dayScale) - 1;  // this would be a lot easier if Sunday was 0 
    int sday = startDay - 1;  

    if (day < sday)  
        day = (day + 7 - sday) % 7;

    return ((day+1) * dayScale) + (date % dayScale);
}

int startDay = startDate / dayScale;  // isolate the day of the week

int normalizedStartDate = NormalizeDate(startDate, startDay);
int normalizedEndDate = NormalizeDate(endDate, startDay);
int normalizedInputDate = NormalizeDate(inputDate, startDay);

inRange = normalizedInputDate >= normalizedStartDate && 
          normalizedInputDate <= normalizedEndDate;

وأنا متأكد من هذا العمل كما هو مكتوب. في أي حال، فإن مفهوم أنظف أن مقارنات متعددة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top