對一個字元按bit位逆序(又稱反轉)
阿新 • • 發佈:2019-02-15
題目要求如題所示:
將一個字元按bit位逆序,例如一個位元組是0x11,將其逆序後就變成0x88。
下面是四種解法,其中最後一種效率最高,是從《Hacker's Delight》這本書中學來的。
第一種:看似創新,其實最笨的做法。使用bit型別,程式碼不夠簡潔,執行效率較低,並且擴充套件不易(例如對int型進行逆序時)。
#define exchange(x,y) { (x) ^= (y); /
(y) ^= (x); /
(x) ^= (y); /
}
unsigned char fun1(unsigned char c)
{
int i;
union {
unsigned char c;
struct{
unsigned char bit0:1;
unsigned char bit1:1;
unsigned char bit2:1;
unsigned char bit3:1;
unsigned char bit4:1;
unsigned char bit5:1;
unsigned char bit6:1;
unsigned char bit7:1;
} bchar;
} ubc;
ubc.c = c;
exchange(ubc.bchar.bit0, ubc.bchar.bit7);
exchange(ubc.bchar.bit1, ubc.bchar.bit6);
exchange(ubc.bchar.bit2, ubc.bchar.bit5);
exchange(ubc.bchar.bit3, ubc.bchar.bit4);
return ubc.c;
}
第二種:傳統思路下的做法。程式碼不是特別簡潔,執行效率也不如下面兩個高效。
unsigned char fun2(unsigned char c)
{
int i =7;
unsigned char tmp =0x01;
unsigned char newc =0x00;
for ( ; i >3; i--) {
newc |= ((c & tmp) << (i - (8- i -1)));
tmp <<=1;
}
for ( ; i >=0; i--) {
newc |= ((c & tmp) >> ((8- i -1) - i));
tmp <<=1;
}
return newc;
}
第三種:靈活變化,思路不錯。新數或之後左移,原數右移。程式碼簡潔度與執行效率都有提升。
unsigned char fun3(unsigned char c)
{
int i;
unsigned char newc =0x00;
for (i =0; i <7; i++) {
newc |= (c &1);
newc <<=1;
c >>=1;
}
return newc;
}
第四種:程式碼簡潔度與執行效率最高的程式碼。
unsigned char fun4(unsigned char c)
{
c = (c &0xaa) >>1| (c &0x55) <<1;
c = (c &0xcc) >>2| (c &0x33) <<2;
c = (c &0xf0) >>4| (c &0x0f) <<4;
return c;
}
將一個字元按bit位逆序,例如一個位元組是0x11,將其逆序後就變成0x88。
下面是四種解法,其中最後一種效率最高,是從《Hacker's Delight》這本書中學來的。
第一種:看似創新,其實最笨的做法。使用bit型別,程式碼不夠簡潔,執行效率較低,並且擴充套件不易(例如對int型進行逆序時)。
#define exchange(x,y) { (x) ^= (y); /
(y) ^= (x); /
(x) ^= (y); /
}
unsigned char fun1(unsigned char c)
{
int i;
union {
unsigned char c;
struct{
unsigned char bit0:1;
unsigned char bit1:1;
unsigned char bit2:1;
unsigned char
unsigned char bit4:1;
unsigned char bit5:1;
unsigned char bit6:1;
unsigned char bit7:1;
} bchar;
} ubc;
ubc.c = c;
exchange(ubc.bchar.bit0, ubc.bchar.bit7);
exchange(ubc.bchar.bit1, ubc.bchar.bit6);
exchange(ubc.bchar.bit3, ubc.bchar.bit4);
return ubc.c;
}
第二種:傳統思路下的做法。程式碼不是特別簡潔,執行效率也不如下面兩個高效。
unsigned char fun2(unsigned char c)
{
int i =7;
unsigned char tmp =0x01;
unsigned char newc =0x00;
for ( ; i >3; i--) {
newc |= ((c & tmp) << (i - (8- i -1)));
tmp <<=1;
}
for ( ; i >=0; i--) {
newc |= ((c & tmp) >> ((8- i -1) - i));
tmp <<=1;
}
return newc;
}
第三種:靈活變化,思路不錯。新數或之後左移,原數右移。程式碼簡潔度與執行效率都有提升。
unsigned char fun3(unsigned char c)
{
int i;
unsigned char newc =0x00;
for (i =0; i <7; i++) {
newc |= (c &1);
newc <<=1;
c >>=1;
}
return newc;
}
第四種:程式碼簡潔度與執行效率最高的程式碼。
unsigned char fun4(unsigned char c)
{
c = (c &0xaa) >>1| (c &0x55) <<1;
c = (c &0xcc) >>2| (c &0x33) <<2;
c = (c &0xf0) >>4| (c &0x0f) <<4;
return c;
}
2008-12-10 附
對於第四種方法,應該更進一步:用巨集定義來實現。
這樣效率更高了 ^_^