16 進数のすべての数字を「反転」する必要があります。すべてのゼロは非ゼロ (F) になり、すべての非ゼロはゼロになります。
私は試した:
void someFunction(DWORD hexVal)
{
//...
hexVal = ~hexVal;
//...
}
これにより、0xE0000000 が 0x0FFFFFFF ではなく 0x1FFFFFFF に変更されました。
どうすれば望ましい結果を得ることができますか?
これにより、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 を追加します。
私が何をしているのか分かりますか?
したがって、反転と否定は 2 つの異なるものです。
反転は各ビットを取り、その補数を次のように生成します。
0xE0000000 = 1110 0000 0000 0000 0000 0000 0000 0000
~0xE0000000 = 0001 1111 1111 1111 1111 1111 1111 1111 = 0x1FFFFFFF
「ゼロ以外のものがゼロになる必要がある」場合は、ブール否定が必要です。
hexVal = !hexVal;
編集:さて、他の回答のいくつかを読んだ後、最終的に質問者が求めていたものを手に入れました。これは、1つの巨大なビット数学式を使用した私の個人的なバージョンです
n = ~(n | ((n & 0x77777777) << 1) | ((n & 0x88888888) >> 3)
| ((n & 0x33333333) << 2) | ((n & 0xCCCCCCCC) >> 2)
| ((n & 0x11111111) << 3) | ((n & 0xEEEEEEEE) >> 1));