Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: BloodSharp en 14 Marzo 2021, 06:51 am



Título: [Solucionado][Consulta / Duda] Desplazando más de 31 bits
Publicado por: BloodSharp en 14 Marzo 2021, 06:51 am
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
  1. #include <cstdio>
  2. #include <cstdint>
  3.  
  4. int64_t SumadorCompleto(int64_t A,int64_t B,uint8_t TamanioBits=(sizeof(int64_t)*8))
  5. {
  6.    int64_t Resultado;
  7.    int64_t PrimeraOp;
  8.    int64_t SegundaOp;
  9.    int64_t i;
  10.    int64_t CarryActual;
  11.    CarryActual^=CarryActual;
  12.    Resultado^=Resultado;
  13.    for(i^=i;i<TamanioBits;i++)
  14.    {
  15.        PrimeraOp=((A>>i)&1)^((B>>i)&1);
  16.        SegundaOp=(PrimeraOp&1)^(CarryActual&1);
  17.        Resultado|=(SegundaOp<<i)&(1<<i);
  18.        CarryActual=(PrimeraOp&1)&&(CarryActual&1)||((((A>>i)&1)&&((B>>i)&1))&1);
  19.    }
  20.    return Resultado;
  21. }
  22.  
  23. int main()
  24. {
  25.    int64_t A=4,B=-7;
  26.    printf("A:%li + B:%li = %li\n",A,B,SumadorCompleto(A,B));
  27.    return 0;
  28. }

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#


Título: Re: [Consulta / Duda] Desplazando más de 31 bits
Publicado por: Eternal Idol en 14 Marzo 2021, 10:30 am
Desplazar no es un problema:
Código
  1. for (int x = 0; x < 64; ++x)
  2.    printf("%d 0x%.I64X\r\n", x, (int64_t)1 << x);

https://en.wikipedia.org/wiki/Two%27s_complement#Addition


Título: Re: [Consulta / Duda] Desplazando más de 31 bits
Publicado por: MAFUS en 14 Marzo 2021, 12:20 pm
Me gustó tu ejercicio. Aquí una solución mía:

Código
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdint.h>
  4.  
  5. uint64_t complemento_a_2(uint64_t num) {
  6.    return (num ^ -1) + 1;
  7. }
  8.  
  9. /**
  10.  * Devuelve el valor de una resta realizada con
  11.  * complemento a dos en forma humana. Los operandos deben
  12.  * ser positivos por trabajar a nivel de bits
  13.  * a: minuendo
  14.  * b: sustraendo
  15.  * c: puntero a la variable que contendrá el resultado
  16.  * retorna: true si el resultado es negativo; false si es positivo
  17.  */
  18. bool resta(uint64_t a, uint64_t b, uint64_t *resultado) {
  19.    bool signo;
  20.  
  21.    *resultado = a + complemento_a_2(b);
  22.    signo = *resultado >> (sizeof(uint64_t) * 8 - 1);
  23.    if(signo) {
  24.        *resultado = complemento_a_2(*resultado);
  25.    }
  26.  
  27.    return signo;
  28. }
  29.  
  30. int main() {
  31.    uint64_t a = 3, b = 7, resultado;
  32.  
  33.    if(resta(a, b, &resultado)) {
  34.        putchar('-');
  35.    }
  36.    printf("%I64u\n", resultado);
  37. }
  38.  


Título: Re: [Consulta / Duda] Desplazando más de 31 bits
Publicado por: BloodSharp en 14 Marzo 2021, 16:47 pm
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
  1. #include <cstdio>
  2. #include <cstdint>
  3.  
  4. int32_t SumadorCompleto(int32_t A,int32_t B,int8_t TamanioBits=(sizeof(int32_t)*8))
  5. {
  6.    int32_t Resultado;
  7.    int32_t PrimeraOp;
  8.    int32_t SegundaOp;
  9.    int32_t i;
  10.    int8_t CarryActual;
  11.    CarryActual^=CarryActual;
  12.    Resultado^=Resultado;
  13.    for(i^=i;i<TamanioBits;i++)
  14.    {
  15.        PrimeraOp=((A>>i)&1)^((B>>i)&1);
  16.        SegundaOp=(PrimeraOp&1)^(CarryActual&1);
  17.        Resultado|=(SegundaOp<<i)&(1<<i);
  18.        CarryActual=(PrimeraOp&1)&&(CarryActual&1)||((((A>>i)&1)&&((B>>i)&1))&1);
  19.    }
  20.    return Resultado;
  21. }
  22.  
  23. int main()
  24. {
  25.    int32_t A=4,B=-7;
  26.    printf("A:%i + B:%i = %i\n",A,B,SumadorCompleto(A,B));
  27.    return 0;
  28. }

(https://i.imgur.com/oRQhcdJ.png)

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


B#


Título: Re: [Consulta / Duda] Desplazando más de 31 bits
Publicado por: RayR en 14 Marzo 2021, 20:04 pm
El problema con 64 bits pasa porque esta expresión:

Código
  1. (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.


Título: Re: [Solucionado][Consulta / Duda] Desplazando más de 31 bits
Publicado por: BloodSharp en 14 Marzo 2021, 23:21 pm
El problema con 64 bits pasa porque esta expresión:

Código
  1. (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#