C 中不带减号的减法

发布于 2024-07-16 01:20:45 字数 48 浏览 7 评论 0原文

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

How can I subtract two integers in C without the - operator?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

五里雾 2024-07-23 01:20:45
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 位开头)。

int a = 34;
int b = 50;

You can convert b to negative value using negation and adding 1:

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

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

-16

This is two's complement sign negation. Processor is doing it when you use '-' operator when you want to negate value or subtrackt it.

Converting float is simpler. Just negate first bit (shoosh gave you example how to do this).

EDIT:

Ok, guys. I give up. Here is my compiler independent version:

#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;
}

I'm using unsigned int so that any compiler will treat it the same.

If you want to subtract negative values, then do it that way:

 unsgined int negative15 = adder(~15, 1);

Now we are completly independent of signed values conventions. In my approach result all ints will be stored as two's complement - so you have to be careful with bigger ints (they have to start with 0 bit).

风为裳 2024-07-23 01:20:45

Pontus 是对的,2 的补码不是 C 标准所强制的(即使它是事实上的硬件标准)。 菲尔的创意答案+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 将取决于您感兴趣的整数类型的宽度(“值位”的数量); 如果未指定,您需要做更多工作才能找到答案!

Pontus is right, 2's complement is not mandated by the C standard (even if it is the de facto hardware standard). +1 for Phil's creative answers; here's another approach to getting -1 without using the standard library or the -- operator.

C mandates three possible representations, so you can sniff which is in operation and get a different -1 for each:

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;

The value 0x7FFFFFFFE would depend on the width (number of ‘value bits’) of the type of integer you were interested in; if unspecified, you have more work to find that out!

何以笙箫默 2024-07-23 01:20:45
  • + 无位设置
  • + 与语言无关
  • + 可以针对不同的数字类型(int、float 等)进行调整
  • - 几乎肯定不是你的 C 作业答案(可能与位有关)

Expand ab:

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

Manufacture -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
  • + No bit setting
  • + Language independent
  • + Can be adjusted for different number types (int, float, etc)
  • - Almost certainly not your C homework answer (which is likely to be about bits)

Expand a-b:

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

Manufacture -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
还在原地等你 2024-07-23 01:20:45
  • + 无位设置
  • + 与语言无关
  • + 与数字类型无关(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)
    

    简化第二项:

    (-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,则ba>0,所以:

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

    所以,如果a总是大于b,那么这将起作用。

  • + No bit setting
  • + Language independent
  • + Independent of number type (int, float, etc)
  • - Requires a>b (ie positive result)
  • - Almost certainly not your C homework answer (which is likely to be about bits)
  • a - b = c

    restricting ourselves to the number space 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)
    

    simplifying the second term:

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

    substituting:

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

    if b>a, then b-a>0, so:

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

    So, if a is always greater than b, then this would work.

    傲娇萝莉攻 2024-07-23 01:20:45

    鉴于 C 中不强制编码整数以支持二进制补码,因此迭代直至完成。 如果他们想让你跳过火圈,没必要提高效率!

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

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

    Given that encoding integers to support two's complement is not mandated in C, iterate until done. If they want you to jump through flaming hoops, no need to be efficient about it!

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

    Silly question... probably silly interview!

    转瞬即逝 2024-07-23 01:20:45

    要在 C 中减去两个整数,您只需要:

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

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

    For subtracting in C two integers you only need:

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

    I don't believe that there is a simple an elegant solution for float or double numbers like for integers. So you can transform your float numbers in arrays and apply an algorithm similar with one simulated here

    以往的大感动 2024-07-23 01:20:45

    如果您想对浮点数执行此操作,请从正数开始并更改其符号位,如下所示:

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

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

    If you want to do it for floats, start from a positive number and change its sign bit like so:

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

    You can also do this for doubles using the appropriate 64 bit integer. in visual studio this is __int64 for instance.

    从﹋此江山别 2024-07-23 01:20:45

    我想这个

    b - a = ~( a + ~b)

    I suppose this

    b - a = ~( a + ~b)

    jJeQQOZ5 2024-07-23 01:20:45

    装配(累加器)样式:

    int result = a;
    result -= b;
    

    Assembly (accumulator) style:

    int result = a;
    result -= b;
    
    合久必婚 2024-07-23 01:20:45

    由于问题要求整数而不是 int ,您可以实现一个小型解释器,而不是使用 教堂数字

    As the question asked for integers not ints, you could implement a small interpreter than uses Church numerals.

    睡美人的小仙女 2024-07-23 01:20:45

    为每个可能的 int-int 情况创建一个查找表!

    Create a lookup table for every possible case of int-int!

    深爱成瘾 2024-07-23 01:20:45

    未测试。 不使用 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;
    }
    

    Not tested. Without using 2's complement:

    #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;
       }
    }
    

    Assuming the length of an int is much less than 255, and the snprintf/sscanf round-trip won't produce any unspecified behavior (right? right?).

    The subtraction can be computed using a - b == a + (-b).


    Alternative:

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

    计㈡愣 2024-07-23 01:20:45

    这可以使用整数溢出:

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

    这也适用于浮点数(假设你制作了浮点数版本......)

    This would work using integer overflow:

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

    This also works for floats (assuming you make a float version…)

    笑,眼淚并存 2024-07-23 01:20:45

    对于任何数据类型的最大范围,补码提供负值减 1 到任何对应值。 例如:
    ~1 --------> -2
    ~2---------> -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] 的值。
    谢谢.....愿这对你有帮助

    For the maximum range of any data type , one's complement provide the negative value decreased by 1 to any corresponding value. ex:
    ~1 --------> -2
    ~2---------> -3
    and so on... I will show you this observation using little code snippet

    #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;
    }
    

    Output: 0
    Note : This is valid only for the range of data type. means for int data type this rule will be applicable only for the value of range[-2,147,483,648 to 2,147,483,647].
    Thankyou .....May this help you

    ︶葆Ⅱㄣ 2024-07-23 01:20:45

    如果

    1. 减数大于或等于0,或者
    2. 被 减数大于或等于0,或者
    3. 减数和被减数小于0

    将被减数乘以-1并将结果添加到减数:

    SUB + (MIN * -1)
    

    否则将被减数乘以 1 并将结果添加到减数。

    SUB + (MIN * 1)
    

    示例(在线尝试):

    #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
    

    Iff:

    1. The Minuend is greater or equal to 0, or
    2. The Subtrahend is greater or equal to 0, or
    3. The Subtrahend and the Minuend are less than 0

    multiply the Minuend by -1 and add the result to the Subtrahend:

    SUB + (MIN * -1)
    

    Else multiply the Minuend by 1 and add the result to the Subtrahend.

    SUB + (MIN * 1)
    

    Example (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) );
    }
    

    Output:

    -1 - -5 = 4
    
    瞄了个咪的 2024-07-23 01:20:45
            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);
    
            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);
    
    两个我 2024-07-23 01:20:45
    void main()
    {
    int a=5;
    int b=7;
    
    while(b--)a--;
    printf("sud=%d",a);
    
    }
    
    void main()
    {
    int a=5;
    int b=7;
    
    while(b--)a--;
    printf("sud=%d",a);
    
    }
    
    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文