さて、私の混乱を一掃し、私の愚かさを自分自身だけでなく他の人にとっても有用な知識に変えようとしています。
主な結論と要約:
この種の最適化はコンパイラーによって自動的に実行されます。この場合、両方のアプローチがx86上の単一のASM命令にコンパイルされます。(上記の投稿を参照)コンパイラーの作業を必要以上に難しくしないでください。ロジックが意味することを実行してください。
いくつかの回答は、これが両方の方法でまったく同じ命令にコンパイルされていることを示しています。
TL; DR
このトピックに関して私が犯した過ちを改善するために、私はこれを自分自身のために、そしてこの質問に奇跡的に悪い答えで答えたときのように精神的な停止に苦しむ人々のために、いくつかの努力を捧げることに決めました...
数値の否定は、アーキテクチャーとデータの表現方法によって異なります。
符号と大きさの表現
どういうわけか、私はこの実装が使用されていると思いました-そうではありません。これは、数値を1つの符号ビットとして表し、残りはすべて値として表します。したがって、-2n - 1-1から2n -1-1までの数値を表すことができ、負のゼロ値もあります。この種の表現では、符号ビットを反転するだけで十分です。
input ^ -0; // as the negative zero has all bits but the MSB as zero
1の補数表現
1の補数の整数表現は、正の表現のビット単位の否定として負の数を表します。ただし、これは実際には使用されていません。8080以降、2つの褒め言葉が使用されます。この表現の奇妙な結果は負のゼロであり、これは多くの問題を引き起こす可能性があります。また、表される数値の範囲は-2n - 1-1から2n- 1-1です。ここで、nは数値が格納されているビット数です。
この場合、数値を否定する最も簡単な「手動」の方法は、符号を表すすべてのビットを反転することです。
input ^ 0xFFFFFFFF; //assuming 32 bits architecture
また
input ^ -0; //as negative zero is a "full one" binary value
2の補数表現
より広く(常に?)使用される表現は、2の補数システムです。これは、-2n -1から2n-1 -1までの数値を表し、ゼロ値は1つだけです。これは、正の範囲を通常のバイナリ表現として表します。ただし、1を2に追加すると(MSB以外のすべてのビットに1があることで表されます)、-2 n -1(MSBでは1になり、他のすべてのビットは0になります)になります。
2の補数を手動で否定するには、すべてのビットを否定して1を加算する必要があります。
(input ^ -1) + 1 //as -1 is represented by all bits as 1
ただし、負の値の範囲は正の値の範囲よりも広いため、この表現では最も負の数に正の数がありません。これらの数を処理するときは、これを考慮に入れる必要があります。最も負の値を反転すると、ゼロの場合と同じように、それ自体が結果になります(簡単にするために、8ビットで)
most negative number: -128, represented as 10000000
inverting all bits: 01111111
adding one: 10000000 -> -128 again
しかし、どうぞ、誰もが*覚えておいてください:時期尚早の最適化はすべての悪の根源です!(オプティマイザーを使用すると、これらはリソースの豊富なアーキテクチャでは過去のものになります)
*:OPはすでにこれを通過しているので、これは私のような他のすべての人のためのものです。
(自己への注意:(時期尚早に)愚かであることは、すべての(正当な)反対票の根源です。)