反转十六进制值的数字
Inverting digits of a hex value
我需要取一个十六进制数中的所有数字并"反转"它们:所有零都变成非零(F),所有非零都变成零。
我试过了:
void someFunction(DWORD hexVal)
{
//...
hexVal = ~hexVal;
//...
}
并且这将0xE0000000改变为0x1FFFFFFF而不是0x0FFFFFFF。
我怎样才能产生想要的结果?
这将为您提供2个字节的所需结果。你得到了4字节的想法。
hexval = ((hexval & 0xf000) ? 0 : 0xf000) |
((hexval & 0xf00) ? 0 : 0xf00) |
((hexval & 0xf0) ? 0 : 0xf0) |
((hexval & 0xf) ? 0 : 0xf);
假设你真的想要零->非零,反之亦然,以数字为基础:
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))
);
}
这是按位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;
}
您可能必须从MSB开始逐字节进行。检查该值是否在16^6和16^7之间(假设它是无符号的)。如果是,请添加到新数字0中。如果不是,添加到新数字2^31+2^30+2^29+2^28。
看到我在说什么了吗?
所以反转和否定是两回事。
反转取每个比特并产生其补码,如下所示:
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));
相关文章:
- 编译器始终打印十六进制/八进制数字
- C++ 在地板函数之后以十六进制打印数字
- 在十六进制中读取的数字在C 中给出了错误的数字
- 将十六进制的数字与零串联
- 从char阵列中提取十六进制数字
- 如何在 c++ 中将十六进制数字转换为字符
- 使用字符串格式限制十六进制数字的数量
- 从输入中找到连续十六进制数字的最大数量
- 努力理解一个以十六进制、十进制、bin 和 dec 计算数字总和的程序
- 将十六进制数字从无符号字符转换为字符串
- 从 bin 文件 -c++ 中读取十六进制数字为每个字符 2 位数字
- 超过两个数字十六进制
- 重载输出运算符给出十六进制数字而不是字符串
- 将十六进制数的 char[] 转换为对应于 ASCII 表中十六进制数字的字母的 char[] 并反转
- 如何获取十六进制数的最后 n 位数字
- 从包含十六进制数字的std::string或QString创建std::bitset或QBitArray
- "first-chance exception..."消息中的十六进制数字是什么意思?
- 反转十六进制值的数字
- int数字中的十六进制*字符
- 数字由 4 个字符组成,十六进制