Primero antes que nada buenos días/noches.
Bueno digamos que estaba muy aburrido :xD y me puse a generar un código que sume en Complemento a 2:
#include <cstdio>
#include <cstdint>
int64_t SumadorCompleto(int64_t A,int64_t B,uint8_t TamanioBits=(sizeof(int64_t)*8))
{
int64_t Resultado;
int64_t PrimeraOp;
int64_t SegundaOp;
int64_t i;
int64_t CarryActual;
CarryActual^=CarryActual;
Resultado^=Resultado;
for(i^=i;i<TamanioBits;i++)
{
PrimeraOp=((A>>i)&1)^((B>>i)&1);
SegundaOp=(PrimeraOp&1)^(CarryActual&1);
Resultado|=(SegundaOp<<i)&(1<<i);
CarryActual=(PrimeraOp&1)&&(CarryActual&1)||((((A>>i)&1)&&((B>>i)&1))&1);
}
return Resultado;
}
int main()
{
int64_t A=4,B=-7;
printf("A:%li + B:%li = %li\n",A,B,SumadorCompleto(A,B));
return 0;
}
Si lo pruebo con ambos números enteros pequeños 4 y 7 el código funciona perfectamente, ahora el problema es cuando pongo un número entero gigante o negativo el código no funciona:
(https://i.imgur.com/5v8vGjB.png)
Dije quizás sea un error de GCC voy a probar otro compilador diferente y de diferente lenguaje como Pascal:
(No puedo subir el código en Pascal porque el foro no lo permite)
(https://i.imgur.com/ewf20Wu.png)
(Solución temporal o hasta que alguien lo verifique lo subo en imagenes)
(https://i.imgur.com/BOaoC5c.png)
(https://i.imgur.com/6rUKm2r.png)
(https://i.imgur.com/jBaAvlX.png)
Lo cuál ocurre lo mismo:
(https://i.imgur.com/f4coZDo.png)
Pero lo que me inquietó es que pasado los 31 bits de desplazamiento no parece realizar operaciones al menos de manera correcta:
(https://i.imgur.com/FT62iKo.png)
Mi duda es hay alguna manera de llegar a desplazar más bits correctamente, o yo tengo algún error y no me dí cuenta todavía del error o ¿También es una limitación de los procesadores esto?
B#
Desplazar no es un problema:
for (int x = 0; x < 64; ++x)
printf("%d 0x%.I64X\r\n", x, (int64_t)1 << x);
https://en.wikipedia.org/wiki/Two%27s_complement#Addition
Me gustó tu ejercicio. Aquí una solución mía:
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
uint64_t complemento_a_2(uint64_t num) {
return (num ^ -1) + 1;
}
/**
* Devuelve el valor de una resta realizada con
* complemento a dos en forma humana. Los operandos deben
* ser positivos por trabajar a nivel de bits
* a: minuendo
* b: sustraendo
* c: puntero a la variable que contendrá el resultado
* retorna: true si el resultado es negativo; false si es positivo
*/
bool resta(uint64_t a, uint64_t b, uint64_t *resultado) {
bool signo;
*resultado = a + complemento_a_2(b);
signo = *resultado >> (sizeof(uint64_t) * 8 - 1);
if(signo) {
*resultado = complemento_a_2(*resultado);
}
return signo;
}
int main() {
uint64_t a = 3, b = 7, resultado;
if(resta(a, b, &resultado)) {
putchar('-');
}
printf("%I64u\n", resultado);
}
Gracias a ambos por responder, he cambiado el código para realizar el mismo problema con operaciones de 32 bits y si funciona perfectamente:
#include <cstdio>
#include <cstdint>
int32_t SumadorCompleto(int32_t A,int32_t B,int8_t TamanioBits=(sizeof(int32_t)*8))
{
int32_t Resultado;
int32_t PrimeraOp;
int32_t SegundaOp;
int32_t i;
int8_t CarryActual;
CarryActual^=CarryActual;
Resultado^=Resultado;
for(i^=i;i<TamanioBits;i++)
{
PrimeraOp=((A>>i)&1)^((B>>i)&1);
SegundaOp=(PrimeraOp&1)^(CarryActual&1);
Resultado|=(SegundaOp<<i)&(1<<i);
CarryActual=(PrimeraOp&1)&&(CarryActual&1)||((((A>>i)&1)&&((B>>i)&1))&1);
}
return Resultado;
}
int main()
{
int32_t A=4,B=-7;
printf("A:%i + B:%i = %i\n",A,B,SumadorCompleto(A,B));
return 0;
}
(https://i.imgur.com/oRQhcdJ.png)
Me doy por vencido :xD espero no necesitar números con 64 bits en mis proyectos reales...
B#
El problema con 64 bits pasa porque esta expresión:
(1<<i)
tiene el tipo del operando izquierdo (la constante literal 1), o sea int. En otras palabras, en realidad estás efectuando el desplazamiento sobre un valor de 32 bits. Si conviertes ese 1 a int64_t, debería funcionar.
Cita de: RayR en 14 Marzo 2021, 20:04 PM
El problema con 64 bits pasa porque esta expresión:
(1<<i)
tiene el tipo del operando izquierdo (la constante literal 1), o sea int. En otras palabras, en realidad estás efectuando el desplazamiento sobre un valor de 32 bits. Si conviertes ese 1 a int64_t, debería funcionar.
Si era eso gracias, tema solucionado. ;-) ;-)
B#