13

演算子なしでCで2つの整数を減算するにはどうすればよい-ですか?

4

17 に答える 17

19
int a = 34;
int b = 50;

否定と1の加算を使用して、bを負の値に変換できます。

int c = a + (~b + 1);

printf("%d\n", c);

-16

これは2の補数の符号の否定です。値を否定したりサブトラックしたりするときに「-」演算子を使用すると、プロセッサがそれを実行します。

フロートの変換は簡単です。最初のビットを否定するだけです(shooshはこれを行う方法の例を示しました)。

編集:

はい、みんな。あきらめる。これが私のコンパイラに依存しないバージョンです:

#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ビットで開始する必要があります)。

于 2009-03-31T08:00:06.300 に答える
13

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 は、関心のある整数型の幅 (「値ビット」の数) によって異なります。指定されていない場合は、それを見つけるためにさらに作業が必要です!

于 2009-03-31T15:26:37.023 に答える
9
  • + ビット設定なし
  • + 言語に依存しない
  • + さまざまな数値タイプ (int、float など) に合わせて調整可能
  • - C の宿題の答えではないことはほぼ間違いありません (ビットに関するものである可能性が高い)。

ab を展開:

ab = a + (-b)
    = a + (-1).b

製造 -1:

float: pi = asin(1.0);
(minusone_flt = sin(3.0/2.0*pi) を使用);
math.h) または = cos(pi)
                  または = log10(0.1)
複雑な: Minusone_cpx = (0,1)**2; // 私は二乗
整数:minusone_int = 0; Minusone_int--; // または上記の float の 1 つを変換します
于 2009-03-31T09:07:58.307 に答える
6

  • + ビット設定なし
  • + 言語に依存しない
  • + 数値型に依存しない (int、float など)
  • - a>b が必要(つまり、肯定的な結果)
  • - C の宿題の答えではないことはほぼ間違いありません (ビットに関するものである可能性が高い)。
  • a - b = c

    数空間 0 <= c < (a+b) に制限します。

           (a - b) mod(a+b) = c mod(a+b)
    a mod(a+b) - b mod(a+b) = c mod(a+b)
    

    第 2 項を単純化すると、次のようになります。

    (-b).mod(a+b) = (a+bb).mod(a+b)
                  = a.mod(a+b)
    

    置換:

    a.mod(a+b) + a.mod(a+b) = c.mod(a+b)
    2a.mod(a+b) = c.mod(a+b)
    

    b>a の場合、ba>0 なので、次のようになります。

    c.mod(a+b) = c
    c = 2a.mod(a+b)
    

    したがって、a が常に b よりも大きい場合、これは機能します。

    于 2009-03-31T08:44:07.133 に答える
    5

    2 の補数をサポートするために整数をエンコードすることは C では義務付けられていないため、完了するまで繰り返します。彼らがあなたに炎の輪を飛び越えてほしいと思っているなら、それについて効率的である必要はありません!

    int subtract(int a, int b)
    {
      if ( b < 0 )
        return a+abs(b);
      while (b-- > 0)
        --a;
      return a;
    }
    

    ばかげた質問...おそらくばかげたインタビュー!

    于 2009-03-31T07:49:42.503 に答える
    3

    Cで2つの整数を減算するには、次のものだけが必要です。

    int subtract(int a, int b)
    {
        return a + (~b) + 1;
    }
    

    整数のように浮動小数点数や倍数の単純でエレガントな解決策があるとは思いません。したがって、浮動小数点数を配列に変換し、ここでシミュレートしたものと同様のアルゴリズムを適用できます。

    于 2009-03-31T08:01:32.820 に答える
    2

    フロートに対してそれを行いたい場合は、正の数から始めて、その符号ビットを次のように変更します。

    float f = 3;
    *(int*)&f |= 0x80000000;
    // now f is -3.
    float m = 4 + f; 
    // m = 1
    

    適切な 64 ビット整数を使用して、double に対してこれを行うこともできます。たとえば、Visual Studio では __int64 です。

    于 2009-03-31T07:59:13.730 に答える
    1

    私はこれを推測します

    b-a =〜(a +〜b)

    于 2009-03-31T08:06:23.540 に答える
    1

    アセンブリ (アキュムレータ) スタイル:

    int result = a;
    result -= b;
    
    于 2009-03-31T08:31:36.787 に答える
    0

    int-intの考えられるすべてのケースのルックアップテーブルを作成します。

    于 2009-04-03T22:29:02.970 に答える
    0

    未検証。2 の補数を使用しない場合:

    #include <stdlib.h>
    #include <stdio.h>
    int sillyNegate(int x) {
       if (x <= 0)
         return abs(x);
       else {
         // setlocale(LC_ALL, "C"); // if necessary.
         char buffer[256];
         snprintf(buffer, 255, "%c%d", 0x2d, x);
         sscanf(buffer, "%d", &x);
         return x;
       }
    }
    

    an の長さがint255 よりはるかに小さく、snprintf/sscanf の往復で不特定の動作が発生しないと仮定します (そうですか?そうですか?)。

    減算は、次を使用して計算できます。a - b == a + (-b).


    別:

    #include <math.h>
    int moreSillyNegate(int x) {
       return x * ilogb(0.5);  // ilogb(0.5) == -1;
    }
    

    于 2010-06-09T10:08:50.710 に答える
    0

    質問で s ではなく整数が求められたため、教会の数字intを使用するよりも小さなインタープリターを実装できます。

    于 2009-03-31T08:27:41.167 に答える
    0

    これは、整数オーバーフローを使用して機能します。

    #include<limits.h>    
    int subtractWithoutMinusSign(int a, int b){
             return a + (b * (INT_MAX + INT_MAX + 1));
    }
    

    これは、float でも機能します (float バージョンを作成すると仮定します…)。

    于 2010-08-13T18:31:27.857 に答える
    -1
    void main()
    {
    int a=5;
    int b=7;
    
    while(b--)a--;
    printf("sud=%d",a);
    
    }
    
    于 2010-07-06T09:54:01.627 に答える
    -1
            int num1, num2, count = 0;
            Console.WriteLine("Enter two numebrs");
            num1 = int.Parse(Console.ReadLine());
            num2 = int.Parse(Console.ReadLine());
            if (num1 < num2)
            {
                num1 = num1 + num2;
                num2 = num1 - num2;
                num1 = num1 - num2;
            }
            for (; num2 < num1; num2++)
            {
                count++;
            }
            Console.WriteLine("The diferrence is " + count);
    
    于 2010-06-09T09:58:28.067 に答える