没有减号的减法

时间:2009-03-31 07:30:04

标签: c

如何在没有-运算符的情况下减去C中的两个整数?

17 个答案:

答案 0 :(得分:16)

int a = 34;
int b = 50;

您可以使用否定并添加1:

将b转换为负值
int c = a + (~b + 1);

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

-16

这是两个补码的否定。当你想使用' - '运算符时,处理器正在执行此操作,以便否定值或对其进行子记录。

转换浮点数更简单。只是否定第一位(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);

现在我们完全独立于签名值约定。在我的方法结果中,所有的整数将被存储为两个补码 - 所以你必须小心更大的整数(它们必须从0位开始)。

答案 1 :(得分:12)

Pontus是对的,C标准没有规定2的补充(即使它是事实上的硬件标准)。 Phil的创意答案+1;这是另一种在不使用标准库或 - 运算符的情况下获得-1的方法。

C要求三种可能的表示形式,因此您可以嗅探正在运行的表示并为每个表示获得不同的-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将取决于您感兴趣的整数类型的宽度('值位数');如果没有说明,你还有更多工作可以找到它!

答案 2 :(得分:7)

  • +无位设置
  • +语言无关
  • +可以针对不同的数字类型(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

答案 3 :(得分:4)

鉴于在C中没有强制要求支持二进制补码的编码整数,所以迭代直到完成。如果他们想让你跳过燃烧的箍,就不需要高效率了!

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

愚蠢的问题......可能是愚蠢的采访!

答案 4 :(得分:3)

如果你想为浮点数做,请从正数开始并改变它的符号位:

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

您也可以使用适当的64位整数对双精度执行此操作。例如,在visual studio中,这是__int64。

答案 5 :(得分:3)

  • +无位设置
  • +语言无关
  • +独立于数字类型(int,float等)
  • - 需要&gt; b (即正面结果)
  • - 几乎肯定不是你的C作业答案(很可能是比特)
  • a - b = c

    将自己限制在数字空间0&lt; = c&lt; (A + B):

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

    简化第二学期:

    (-b).mod(a+b) = (a+b-b).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,则b-a> 0,所以:

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

    所以,如果a总是大于b,那么这就行了。

    答案 6 :(得分:1)

    汇编(累加器)样式:

    int result = a;
    result -= b;
    

    答案 7 :(得分:1)

    我想这个

    b - a =〜(a + ~b)

    答案 8 :(得分:1)

    为了在C中减去两个整数,你只需要:

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

    我不相信有一个简单优雅的浮点数或双数字解决方案,如整数。因此,您可以在数组中转换浮点数并应用与模拟here

    类似的算法

    答案 9 :(得分:0)

    由于问题是整数而不是int s,你可以实现一个小解释器,而不是使用Church numerals

    答案 10 :(得分:0)

    为每个可能的int-int案例创建一个查找表!

    答案 11 :(得分: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;
       }
    }
    

    假设int的长度远小于255,并且snprintf / sscanf往返不会产生任何未指定的行为(对吗?对吧?)。

    可以使用a - b == a + (-b).

    计算减法

    替代:

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

    答案 12 :(得分:0)

    这可以使用整数溢出:

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

    这也适用于花车(假设您制作浮动版......)

    答案 13 :(得分:0)

    对于任何数据类型的最大范围,一个补码提供的负值减少1到任何相应的值。例如:
    ~1 --------&gt; -2
    〜2 ---------&GT; -3
    等等......我会用一些代码片段向你展示这个观察结果

    #include<stdio.h>
    int main()
    {
       int a , b;
       a=10;
       b=~a; // b-----> -11    
       printf("%d\n",a+~b+1);// equivalent to a-b
       return 0;
    }
    

    输出:0
    注意:这仅适用于数据类型范围。对于int数据类型的含义,此规则仅适用于范围[-2,147,483,648到2,147,483,647]的值。 谢谢.....这可以帮到你

    答案 14 :(得分:0)

    Iff

    1. Minuend大于或等于0
    2. Subtrahend大于或等于0
    3. Subtrahend和Minuend小于0

    将Minuend乘以-1,然后将结果添加到Subtrahend:

    SUB + (MIN * -1)
    

    否则,将Minuend乘以1,然后将结果添加到Subtrahend。

    SUB + (MIN * 1)
    

    示例(Try it online):

    #include <stdio.h>
    
    int subtract (int a, int b)
    {
        if ( a >= 0 || b >= 0 || ( a < 0 && b < 0 ) )
        {
            return a + (b * -1);
        }
    
        return a + (b * 1); 
    }
    
    int main (void)
    {
        int x = -1;
        int y = -5;
        printf("%d - %d = %d", x, y, subtract(x, y) );
    }
    

    输出:

    -1 - -5 = 4
    

    答案 15 :(得分:-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);
    

    答案 16 :(得分:-1)

    void main()
    {
    int a=5;
    int b=7;
    
    while(b--)a--;
    printf("sud=%d",a);
    
    }