C++ 十六进制值的倒位数字

C++ 十六进制值的倒位数字,c++,hex,C++,Hex,我需要取一个十六进制数中的所有数字并“反转”它们:所有的零变成非零(F),所有的非零变成零 我试过: void someFunction(DWORD hexVal) { //... hexVal = ~hexVal; //... } 这将0xE0000000更改为0x1FFFFFF,而不是0x0FFFFFFF 如何生成所需的结果?这是按位NOT操作所需的结果。0xE0000000+0x1FFFFFF=0xFFFFFFFF 做你想做的事情最快的方法就是把它分成字节,

我需要取一个十六进制数中的所有数字并“反转”它们:所有的零变成非零(F),所有的非零变成零

我试过:

void someFunction(DWORD hexVal)
{
     //...
     hexVal = ~hexVal;
     //...
}
这将0xE0000000更改为0x1FFFFFF,而不是0x0FFFFFFF


如何生成所需的结果?

这是按位NOT操作所需的结果。0xE0000000+0x1FFFFFF=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;
}
unsigned int transform1(unsigned int value)
{
//静态const unchar char ZZ= 0x0,ZF= 0xf,fz=0xf0,ff= 0xFF;//对于C++
#定义ZZ(无符号字符)0x00
#定义FZ(无符号字符)0xF0
#定义ZF(无符号字符)0x0F
#定义FF(无符号字符)0xFF
静态常量无符号字符查找[256]=
{
FF,FZ,FZ,FZ,FZ,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,ZZ,ZZ,ZZ,ZZ,
ZF,ZZ,ZZ,ZZ,ZZ,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,ZZ,ZZ,ZZ,ZZ,
ZF,ZZ,ZZ,ZZ,ZZ,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,ZZ,ZZ,ZZ,ZZ,
ZF,ZZ,ZZ,ZZ,ZZ,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,ZZ,ZZ,ZZ,ZZ,
ZF,ZZ,ZZ,ZZ,ZZ,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,ZZ,ZZ,ZZ,ZZ,
ZF,ZZ,ZZ,ZZ,ZZ,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,ZZ,ZZ,ZZ,ZZ,
ZF,ZZ,ZZ,ZZ,ZZ,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,ZZ,ZZ,ZZ,ZZ,
ZF,ZZ,ZZ,ZZ,ZZ,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,ZZ,ZZ,ZZ,ZZ,
};//阵列占用1KB的RAM
无符号整数结果=0;

结果|=lookup[(unsigned int)((value&(FF>0)]8)]16)]24]您可能必须从MSB开始逐字节查找。检查该值是否介于16^6和16^7之间(假设为unsigned)。如果是,则添加到新数字0。如果不是,则添加到新数字2^31+2^30+2^29+2^28


明白我的意思了吗?

这将为您提供2个字节所需的结果。您得到了4个字节的想法

hexval = ((hexval & 0xf000) ? 0 : 0xf000) |
         ((hexval & 0xf00) ? 0 : 0xf00) |
         ((hexval & 0xf0) ? 0 : 0xf0) |
         ((hexval & 0xf) ? 0 : 0xf);

所以倒装和否定是两码事

反转取每个位并生成其补码,如下所示:

 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));
n=~(n |)((n&0x7777)>3)
|((n&0x33333)>2)
|((n&0x11111111)>1));

假设您真的想要零->非零,反之亦然,以数字为单位:

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))
    );
}
DWORD反转数字(DWORD in){
返回(

(在,(0xF 0xE0000000不是0x00000000?@我知道,调用函数的程序通过了0xE0000000@jli非零值在反转后不必是F,它可以是任何非零值。除零以外的任何值都需要变为零
0xE0000000=1110 0000 0000 0000
~0xE0000000=0001 1111 1111 1111 1111 1111 1111 1111 1111 1111 11111111=0x1ffffff
在我看来,你需要将这些四分之一的比特放入循环中,并单独处理它们。这在语法上不是很有效。有时。这取决于编译器认为const的大小。现在,它是C兼容的。主要是。这在你的机器上运行得有多快?没有线索。我正在运行windows atm,因为linux和amd拒绝合作。然而,在我做的web测试中,它在大约.55秒内运行了100万次迭代。在问题的评论中有一个指向测试的链接,只需克隆它并使用转换函数。我很惊讶,当我看到它时,我认为你的速度会更快。出于厌倦,我尝试了一个16位的查找表,它可以使用fa这里列出了所有的解决方案,100米回合的成绩略低于0.4秒(10亿回合成绩为3.97秒)。我在运行时初始化了查找表,这增加了额外的一次性性能影响。如果有人好奇,请注意:您的偏移量不够。位偏移量。:DIt似乎返回了正确的答案。但我没有完全测试它。在.8秒内运行了1亿次迭代。在1亿次迭代中大约1.2秒。Han Z'解决方案稍微快一点。@Wug这是因为bitmath和bitshift>branching;)这是几次运行的平均值1.2秒吗(因为运行的其他程序可能会影响它)?我不担心每次迭代使用1.2*10^-8(在您的平台/OS/上,取决于运行的其他程序)。您的程序可能会在其他地方提高性能。