C のマイナス記号なしの減算

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