using bitwise operation to extract month from int

2019-09-21 16:14发布

问题:

Is it possible to extract the month from date represented as int (format YYYYMMDD, e.g. 20110401) using some bitwise operators?

If so, how can it be done?

edit: I am currently using 20110401 % 10000 / 100. I thought bit-wise could be faster. DateTime.Parse etc. are too slow for what I am trying to do.

回答1:

You could efficiently extract the month with bitwise operations if you represented the date in a binary format, e.g., 5 bits for the day of the month, 4 bits for the month number, and the rest for the year, rather than as decimal digits. For your example, the date would be (2011 << 9) + (4 << 5) + 1 (which of course is not equal to 20110401). To use bitwise operations to extract the fields from such a representation:

int year = date >> 9;
int month = (date >> 5) & 0xF;
int day = date & 0x1F;

Another approach, as mentioned by Mark Byers, is to use a struct, e.g.,

typedef struct {
    short year;
    char  month;
    char  day;
} Date;

You can pass these around on the stack, extract the fields by name, and initialize them as

Date d = { 2011, 4, 1};

or, in C99,

Date d = { .year = 2011, .month = 4, .day = 1 };


回答2:

No, because bitwise operators work with the binary representation of the number. Your date is encoded using a decimal representation.

You can do it using arithmetic operators though:

int date = 20110401;

int day = date % 100;
int month = (date / 100) % 100;
int year = date / 10000;


回答3:

20110301 (base 10) as an integer will be represented quite differently at the bit-level, in fact as 1001100101101101111011101 (base 2). Using bit level operations to extract the month from this bit-string is not going to be straight forward.

Alternatives:

  • Do some basic math involving mod on the integer

  • Convert the int into a string and then extract the relevant digits and convert them back to integers.

  • Or better yet, to use some already tested library functions for this.

Bit level operations are not a good approach for this problem.



回答4:

Using bitwise operations would probably be error prone, if you could do it at all. You can do it by manipulating the number with division and modulo operations.

You could also convert it to a string, parse the the month characters, and then convert back to an int.

Here's some example code in C#

int date = 20119420;
int month = 0;

// using good old math
month = (date / 100) % 100;

// using string parsing
month = int.Parse(date.ToString().Substring(4, 2));


回答5:

So I know this is an extremely old post but this was actually an assignment for our class, I have a compress date and an extract date function using only bitwise operations:

    //Compress Date
    int compressDate(int month, int day, int year)
    {
        int date = year;
        date <<= 4;
        date |= month;
        date <<= 6;
        date |= day;

        return date;

    }

    //Extract Date
    void extractDate(int date, int& month, int& day, int& year)
    {
        int dayMask = 63;
        int monthMask = 15;
        int yearMask = 4095;


        day = date & dayMask;
        date >>= 6;
        month = date & monthMask;
        date >>= 4;
        year = date & yearMask;
    }

When you execute the compress date function with something like compressDate(1, 25, 2019), it returns the number: 2067545 and the extractDate function just works in the opposite order. The reason for doing this is that bitwise operators are faster than using math operators.