Solución:
int a = 34;
int b = 50;
Puede convertir b a valor negativo usando la negación y agregando 1:
int c = a + (~b + 1);
printf("%dn", c);
-16
Esta es la negación del signo del complemento a dos. El procesador lo está haciendo cuando usa el operador ‘-‘ cuando desea negar el valor o restarlo.
Convertir el flotador es más sencillo. Simplemente niegue el primer bit (shoosh le dio un ejemplo de cómo hacer esto).
EDITAR:
Ok muchachos. Me rindo. Aquí está mi versión independiente del compilador:
#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 = %dn", a, b, sub(a, b)); // printf function isn't compiler independent here
return 0;
}
Estoy usando unsigned int para que cualquier compilador lo trate de la misma manera.
Si desea restar valores negativos, hágalo de esa manera:
unsgined int negative15 = adder(~15, 1);
Ahora somos completamente independientes de las convenciones de valores con signo. En mi enfoque, el resultado de todos los ints se almacenarán como complemento de dos, por lo que debe tener cuidado con los ints más grandes (deben comenzar con 0 bit).
Pontus tiene razón, el complemento de 2 no es obligatorio por el estándar C (incluso si es el estándar de hardware de facto). +1 por las respuestas creativas de Phil; aquí hay otro enfoque para obtener -1 sin usar la biblioteca estándar o el operador -.
C exige tres representaciones posibles, por lo que puede olfatear cuál está en funcionamiento y obtener un -1 diferente para cada una:
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;
El valor 0x7FFFFFFFE dependería del ancho (número de ‘bits de valor’) del tipo de entero que le interesa; si no se especifica, ¡tienes más trabajo para averiguarlo!
- + Sin ajuste de bits
- + Independiente del idioma
- + Se puede ajustar para diferentes tipos de números (int, float, etc.)
- – Es casi seguro que no sea la respuesta de la tarea de C (que probablemente se trate de bits)
Expandir ab:
a-b = a + (-b) = a + (-1).b
Fabricación -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