[Solucionado][Consulta / Duda] Desplazando más de 31 bits

Iniciado por BloodSharp, 14 Marzo 2021, 06:51 AM

0 Miembros y 1 Visitante están viendo este tema.

BloodSharp

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:

Código (cpp) [Seleccionar]
#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:



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)

(Solución temporal o hasta que alguien lo verifique lo subo en imagenes)




Lo cuál ocurre lo mismo:



Pero lo que me inquietó es que pasado los 31 bits de desplazamiento no parece realizar operaciones al menos de manera correcta:



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#



Eternal Idol

Desplazar no es un problema:
Código (c++) [Seleccionar]
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
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

MAFUS

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);
}

BloodSharp

Gracias a ambos por responder, he cambiado el código para realizar el mismo problema con operaciones de 32 bits y si funciona perfectamente:

Código (cpp) [Seleccionar]
#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;
}




Me doy por vencido :xD espero no necesitar números con 64 bits en mis proyectos reales...


B#



RayR

#4
El problema con 64 bits pasa porque esta expresión:

Código (cpp) [Seleccionar]
(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.

BloodSharp

Cita de: RayR en 14 Marzo 2021, 20:04 PM
El problema con 64 bits pasa porque esta expresión:

Código (cpp) [Seleccionar]
(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#