Re: Хэш для диапазона дат
От: kov_serg Россия  
Дата: 23.03.17 12:36
Оценка: 105 (1)
Здравствуйте, busk, Вы писали:


B>Есть интервал в виде дат — два поля. Надо сделать что то типа хэша для данного диапазона чтобы потом можно было сравнивая два хэша сказать, что они пересекаются.


Нет проблем. Надо примерно равномерный хэш для диапазона дат. Можно как-то так сделать (предполагается что в диапазоне конечная дата не включается т.е [h,t) )
#include <stdio.h>

typedef unsigned long long uint64;

int encodeDate(int Year,int Month,int Day) {
    int c,ya;
    if (Month > 2) Month-=3; else { Month+=9;Year--; }
    c =Year/100;
    ya=Year-100*c;
    c =(146097*c)/4 + (1461*ya)/4 + (153*Month+2)/5 + Day + 1721119;
    return c;
}
void decodeDate(int date,int &Year,int &Month,int &Day) {
    date -= 1721119;
    Year  = (4*date-1)/146097;
    Day   = (4*date-1-146097*Year)/4;
    date  = (4*Day+3)/1461;
    Day   = (4*Day+7-1461*date)/4;
    Month = (5*Day-3)/153;
    Day   = (5*Day+2-153*Month)/5;
    Year  = 100*Year + date;
    if (Month < 10) Month+=3; else { Month-=9;Year++; }
}
uint64 pack(int h,int t) { return ((uint64)h<<32)|t; }
void unpack(uint64 v,int &h,int &t) { h=v>>32; t=v; }
uint64 enc(uint64 x) { return x*0x5DE942361AD6BFCBULL; } // замешиваем, можно разными способами
uint64 dec(uint64 x) { return x*0x6ACB5A03516FEDE3ULL; } // востанавливаем

uint64 hashDateRange(int y1,int m1,int d1, int y2,int m2,int d2) {
    return enc(pack( encodeDate(y1,m1,d1), encodeDate(y2,m2,d2) ));
}

int isIntersect(uint64 c1,uint64 c2) {
    int h1,h2,t1,t2;
    unpack(dec(c1),h1,t1);
    unpack(dec(c2),h2,t2);
    if (h2>h1) h1=h2;
    if (t2<t1) t1=t2;
    return h1<t1;
}

int main(int argc,char** argv) {
    uint64 hash1,hash2; int i1;

    hash1=hashDateRange(2010,1,1, 2012,2,1);
    hash2=hashDateRange(2011,1,1, 2011,1,2);

    i1=isIntersect(hash1,hash2);
    printf("hash1=%016llX hash2=%016llX intersect=%d\n",hash1,hash2,i1);

    return 0;
}

hash1=7BFC72ED0DA913BD hash2=D942BDE0A44F2584 intersect=1
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.