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
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!