int a = 34;
int b = 50;
否定と 1 の追加を使用して、b を負の値に変換できます:
int c = a + (~b + 1);
printf("%d\n", c);
-16
これは 2 の補数の符号否定です。値を否定したりサブトラックしたいときに「-」演算子を使用すると、プロセッサがそれを実行します。
float の変換はより簡単です。最初のビットを否定するだけです (シューシュはこれを行う方法の例を示しました)。
編集:
わかりました、皆さん。あきらめる。これが私のコンパイラに依存しないバージョンです:
#include <stdio.h>
unsigned int adder(unsigned int a, unsigned int b) {
unsigned int loop = 1;
unsigned int sum = 0;
unsigned int ai, bi, ci;
while (loop) {
ai = a & loop;
bi = b & loop;
ci = sum & loop;
sum = sum ^ ai ^ bi; // add i-th bit of a and b, and add carry bit stored in sum i-th bit
loop = loop << 1;
if ((ai&bi)|(ci&ai)|(ci&bi)) sum = sum^loop; // add carry bit
}
return sum;
}
unsigned int sub(unsigned int a, unsigned int b) {
return adder(a, adder(~b, 1)); // add negation + 1 (two's complement here)
}
int main() {
unsigned int a = 35;
unsigned int b = 40;
printf("%u - %u = %d\n", a, b, sub(a, b)); // printf function isn't compiler independent here
return 0;
}
どのコンパイラでも同じように扱われるように、unsigned int を使用しています。
負の値を減算する場合は、次のようにします。
unsgined int negative15 = adder(~15, 1);
これで、符号付き値の規則から完全に独立しました。私のアプローチの結果では、すべての int が 2 の補数として格納されます。そのため、より大きな int には注意する必要があります (0 ビットから開始する必要があります)。
Pontus の言う通り、2 の補数は C 標準では義務付けられていません (事実上のハードウェア標準であっても)。 +1 フィルの創造的な答え;標準ライブラリや -- 演算子を使用せずに -1 を取得する別の方法を次に示します。
C では 3 つの可能な表現が義務付けられているため、どれが動作しているかを嗅ぎ分けて、それぞれに異なる -1 を取得できます。
negation= ~1;
if (negation+1==0) /* one's complement arithmetic */
minusone= ~1;
else if (negation+2==0) /* two's complement arithmetic */
minusone= ~0;
else /* sign-and-magnitude arithmetic */
minusone= ~0x7FFFFFFE;
r= a+b*minusone;
値 0x7FFFFFFFE は、関心のある整数型の幅 (「値ビット」の数) に依存します。指定されていない場合は、それを見つけるためにさらに作業が必要です!
- + ビット設定なし
- + 言語に依存しない
- + さまざまな数値タイプ (int、float など) に合わせて調整可能
- - C の宿題の答えではないことはほぼ間違いありません (ビット程度の可能性があります)
a-b を展開:
a-b = a + (-b) = a + (-1).b
製造 -1:
float: pi = asin(1.0); (with minusone_flt = sin(3.0/2.0*pi); math.h) or = cos(pi) or = log10(0.1) complex: minusone_cpx = (0,1)**2; // i squared integer: minusone_int = 0; minusone_int--; // or convert one of the floats above