我需要取十六进制数字中的所有数字并“反转”它们:全零变为非零(F),所有非零变为零。
我试过了:
void someFunction(DWORD hexVal)
{
//...
hexVal = ~hexVal;
//...
}
这将0xE0000000更改为0x1FFFFFFF而不是0x0FFFFFFF。
如何产生所需的结果?
答案 0 :(得分:3)
这应该为您提供2个字节的所需结果。你明白了4个字节。
hexval = ((hexval & 0xf000) ? 0 : 0xf000) |
((hexval & 0xf00) ? 0 : 0xf00) |
((hexval & 0xf0) ? 0 : 0xf0) |
((hexval & 0xf) ? 0 : 0xf);
答案 1 :(得分:3)
假设你真的意味着你想要零 - >非零,反之亦然,逐个数字:
DWORD invertDigits(DWORD in) {
return (
((in & (0xF << 28)) ? 0x0 : (0xF << 28)) |
((in & (0xF << 24)) ? 0x0 : (0xF << 24)) |
((in & (0xF << 20)) ? 0x0 : (0xF << 20)) |
((in & (0xF << 16)) ? 0x0 : (0xF << 16)) |
((in & (0xF << 12)) ? 0x0 : (0xF << 12)) |
((in & (0xF << 8)) ? 0x0 : (0xF << 8)) |
((in & (0xF << 4)) ? 0x0 : (0xF << 4)) |
((in & (0xF << 0)) ? 0x0 : (0xF << 0))
);
}
答案 2 :(得分:2)
这是按位NOT运算的期望结果。 0xE0000000 + 0x1FFFFFFF = 0xFFFFFFFF
执行所需操作的绝对最快方法是将其拆分为字节并使用查找表。
此解决方案使处理器相当于:24次添加,4次乘法和4次内存查找。乘法是数组索引的一部分。所有简单的数学运算都以大约相同的速度运行,除了稍微长一些的乘法和内存查找。您的里程可能会有所不同,具体取决于您的处理器架构和执行的编译器优化。
unsigned int transform1(unsigned int value)
{
// static const unsigned char ZZ = 0x0, ZF = 0xF, FZ = 0xF0, FF = 0xFF; // for C++
#define ZZ (unsigned char) 0x00
#define FZ (unsigned char) 0xF0
#define ZF (unsigned char) 0x0F
#define FF (unsigned char) 0xFF
static const unsigned char lookup[256] =
{
FF, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ, FZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
ZF, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ, ZZ,
}; // array takes up 1KB of RAM
unsigned int result = 0;
result |= lookup[(unsigned int)((value & (FF << 0 )) >> 0) ] << 0;
result |= lookup[(unsigned int)((value & (FF << 8 )) >> 8) ] << 8;
result |= lookup[(unsigned int)((value & (FF << 16)) >> 16)] << 16;
result |= lookup[(unsigned int)((value & (FF << 24)) >> 24)] << 24;
return result;
}
答案 3 :(得分:0)
从MSB开始,您可能必须逐字节地进行操作。检查值是否在16 ^ 6和16 ^ 7之间(假设这是无符号的)。如果是,请添加到新号码0.如果不是,请添加新号码2 ^ 31 + 2 ^ 30 + 2 ^ 29 + 2 ^ 28。
看看我的目标是什么?
答案 4 :(得分:0)
所以反转和否定是两回事。
反转取每一位并产生其补码:
0xE0000000 = 1110 0000 0000 0000 0000 0000 0000 0000
~0xE0000000 = 0001 1111 1111 1111 1111 1111 1111 1111 = 0x1FFFFFFF
如果你想要“零以外的任何东西需要变为零”你想要布尔否定,即
hexVal = !hexVal;
编辑:好的,所以在阅读了其他一些答案之后,我终于得到了提问者的问题,这是我的个人版本,使用了一个巨大的数学表达式
n = ~(n | ((n & 0x77777777) << 1) | ((n & 0x88888888) >> 3)
| ((n & 0x33333333) << 2) | ((n & 0xCCCCCCCC) >> 2)
| ((n & 0x11111111) << 3) | ((n & 0xEEEEEEEE) >> 1));