Subtraction without minus sign in C

  • + 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

  • + 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.


    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).


    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!