没有减号的减法

Syn*_*ter 11 c

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

kle*_*lew 16

int a = 34;
int b = 50;
Run Code Online (Sandbox Code Playgroud)

您可以使用否定并添加1将b转换为负值:

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

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

-16
Run Code Online (Sandbox Code Playgroud)

这是两个补码的否定.处理器在您使用' - '运算符时执行此操作,当您想要否定值或将其删除时.

转换浮点数更简单.只是否定第一位(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;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用unsigned int,因此任何编译器都会对它进行相同的处理.

如果要减去负值,请按以下方式执行:

 unsgined int negative15 = adder(~15, 1);
Run Code Online (Sandbox Code Playgroud)

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


bob*_*nce 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;
Run Code Online (Sandbox Code Playgroud)

值0x7FFFFFFFE将取决于您感兴趣的整数类型的宽度('值位数'); 如果没有说明,你还有更多工作可以找到它!


Phi*_*l H 7

  • +没有位设置
  • +语言独立
  • +可以针对不同的数字类型进行调整(int,float等)
  • - 几乎肯定不是你的C作业答案(很可能是关于比特)

展开ab:

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


Phi*_*l H 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)
    

    简化第二项:

    (-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,那么这将起作用。


    Pon*_*gge 5

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

    int subtract(int a, int b)
    {
      if ( b < 0 )
        return a+abs(b);
      while (b-- > 0)
        --a;
      return a;
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

    • 顺便说一句,您使用的是“-”运算符,但隐藏在“--”运算符中。 (3认同)
    • &lt;LanguageLawyer&gt;不,根据定义,两个独立的运算符。令牌恰好由相同的 ASCII 代码表示!(问题中的未定条件是禁止使用二进制“-”还是禁止使用一元“-”。)&lt;/LanguageLawyer&gt; (2认同)