Problema en variable int

Iniciado por meoit ARG, 28 Abril 2014, 21:56 PM

0 Miembros y 2 Visitantes están viendo este tema.

eferion

Eres un exagerado. Su funcionamiento tampoco es tan complicado.

Lo único que hace la clase es almacenar el número en un vector de tipo "unsigned int". Lo he hecho así porque las operaciones matemáticas sobre tipos int o uint son más rápidas que ir carácter a carácter ( en el caso de almacenar el número en un string )... además, como efecto secundario, consume menos memoria.

amchacon

En la función toString ¿Que son estas lineas?
Código (cpp) [Seleccionar]
to_return = Mul2AddN( to_return, (data & 0x80000000)? 1 : 0 );
data <<= 1;


¿Y binTostring que hace? ¿Imprimir el valor de los bits?
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

vangodp

¿ves lo que digo?  :laugh: :laugh: :laugh:

Puede que tu digas que tu código no sea para tanto :laugh: lo que no sabes es lo limitado que es la gente detrás de la pantalla. :D
Cuando el saber hace parte de tu día a día ignoras que la gente no sabe tanto como tu, te imaginas que todos tenemos la misma capacidad pero en realidad a algunos nos cuesta mas que a otros. Tener paciencia con nosotros lo novatos.  ;D
Lo que haces es grande, ayudas a la gente y no exiges nada a cambio, yo no podría pagar semejante ayuda con dinero. Así que al menos digo ¡¡¡Gracias*1000!!! ;-)

No soy grande...camino junto a ellos ^^

eferion

#13
La función BinToString convierte a string la representación binaria del número.

Tal y como están estructurados los datos me parecía que era más fácil calcular la representación en base 10 de la siguiente forma:

* Creo un string con valor por defecto: "0"
* Recorro el array binario, empezando por los bits de mayor peso.
* Para cada iteración, multiplico el resultado del string por 2.
* Si el bit de turno en la iteración es '1', se lo sumo al string del resultado.

Los dos últimos pasos se realizan conjuntamente con la función Mul2AddN ( lo que viene a significar, multiplica por dos y suma N, donde N será 0 o 1 según proceda ).

la expresión:

Código (cpp) [Seleccionar]
(data & 0x80000000 )? 1 : 0

sirve para evaluar el bit de mayor peso de cada "tramo" de "unsigned int"... recordemos que está toda la representación metida en un vector.

Para poder evaluar los 32 bits de cada tramo tengo que hacer un desplazamiento binario, sustituyendo el bit de mayor peso por el siguiente... esto se hace con la siguiente línea:

Código (cpp) [Seleccionar]
data <<= 1;

Dicho con un ejemplo práctico la mecánica es la siguiente:


Número en binario: 1100101
resultado inicial: "0"

1a iteracion:
 "data & 0x800...": 1
 resultado = "0" * 2 + 1 = "1"

2a iteracion:
 "Data & 0x800...": 1
 resultado = "1" * 2 + 1 = "3"

3a iteracion:
 "Data & 0x800...": 0
 resultado = "3" * 2 + 0 = "6"

4a iteracion:
 "Data & 0x800...": 0
 resultado = "6" * 2 + 0 = "12"

5a iteracion:
 "Data & 0x800...": 1
 resultado = "12" * 2 + 1 = "25"

6a iteracion:
 "Data & 0x800...": 0
 resultado = "25" * 2 + 0 = "50"

7a iteracion:
 "Data & 0x800...": 1
 resultado = "50" * 2 + 1 = "101"

resultado final: "101"


modificado:

Cita de: vangodp en 29 Abril 2014, 15:51 PM
¿ves lo que digo?  :laugh: :laugh: :laugh:

Puede que tu digas que tu código no sea para tanto :laugh: lo que no sabes es lo limitado que es la gente detrás de la pantalla. :D
Cuando el saber hace parte de tu día a día ignoras que la gente no sabe tanto como tu, te imaginas que todos tenemos la misma capacidad pero en realidad a algunos nos cuesta mas que a otros. Tener paciencia con nosotros lo novatos.  ;D
Lo que haces es grande, ayudas a la gente y no exiges nada a cambio, yo no podría pagar semejante ayuda con dinero. Así que al menos digo ¡¡¡Gracias*1000!!! ;-)

No soy grande...camino junto a ellos ^^

Tu comentario me halaga, no lo puedo negar. Pero casi me pones a la altura de un semidios o algo así y tampoco es para tanto.

Muchas veces, cosas de estas son del tipo "idea feliz"... cuando las comprendes, ves que muchísimas veces la solución es más sencilla de lo que aparenta.

En cualquier caso, también ha quedado claro en algunos hilos que no soy infalible... sobretodo si posteo desde el móvil XDDDDD. Pero bueno, se hace lo que se puede con tal de ayudar.

Un saludo.

Blaster

Y el 0x80000000 de donde lo sacaste, que valor tiene y por que necesariamente debe ser este el indicado para hacer la comparación binario con dato

Saludos..

eferion

Cita de: Blaster en 29 Abril 2014, 16:47 PM
Y el 0x80000000 de donde lo sacaste, que valor tiene y por que necesariamente debe ser este el indicado para hacer la comparación binario con dato

Saludos..

Un int típico son 32 bytes. Unsigned int usa los mismos 32 bits, la diferencia es que al no usar bit de signo, amplía el rango posible de valores positivos.

Si tu pasas el número 0x80000000 a binario tienes el número:


8    0    0    0    0    0    0    0
1000 0000 0000 0000 0000 0000 0000 0000


Como ves, esa "máscara" junto con el operador binario and "&" permite saber si el dígito de mayor peso de una secuencia de 32 bits es 1 o 0... "X & 0x80000000" únicamente arrojará un resultado diferente a 0 cuando el bit de mayor peso sea 1... independientemente del estado del resto de los bits.

Si el tipo unsigned int ocupase un tamaño diferente a los ya comentados 32 bits habría que reajustar la máscara.

leosansan

#16
Cita de: eferion en 29 Abril 2014, 10:14 AM
¿Y hacerte una clase para manejar números grandes?

...............................................................................

Si estás programando en C el tema de las clases ya no te sirve... pero aún así sigue habiendo opciones.


Bueno si se trata de sumar números grandes en C, aunque no es necesaria, mejor con una función por si nos da por ampliar a resta, producto, etc y con arrays.

Y como comentó eferion:


Cita de: eferion en 29 Abril 2014, 11:41 AM

Como es de esperar... ni está optimizada ni completa... está hecha en un rato para satisfacer el insaciable apetito de vangodp... pero vale de ejemplo.


Todo por un colega como vangodp, ahí va mi más que modesta propuesta en C:

Código (cpp) [Seleccionar]
#include <stdio.h>
#include <string.h>

#define MAX_DIGITOS 200

void suma (char a[], char b[], char c[]){
 int i,temp,residuo=0,lon_a,lon_b,dif;
 lon_a = strlen(a);
 lon_b = strlen(b);
 if (lon_a > lon_b){
   dif=lon_a-lon_b;
   for (i=lon_b-1; i >=0;i--)
     b[i+dif]=b[i];
   for (i=0; i < dif;i++)
       b[i]='0';
 }
 else if (lon_b > lon_a){
   dif=lon_b-lon_a;
   for (i=lon_a-1; i >=0;i--)
     a[i+dif]=a[i];
   for (i=0; i < dif;i++)
       a[i]='0';
 }
 for (i=strlen(a)-1; i>=0;i-- ){
   temp = a[i]-'0' + b[i]-'0' + residuo;
   c[i+1]=temp%10+'0';
   residuo=temp/10;
 }
 c[0] = residuo + '0';
 if (c[0]=='0'){
   for (i=0; i < strlen(a);i++ ){
     c[i]=c[i+1];
   }
   c[strlen(a)]='\0';
 }
 c[strlen(a)+1]='\0';
}

int main(void){
 char a[MAX_DIGITOS] = /*  "99" */ /* "99" */ "123456123456123456123456123456123123";
 char b[MAX_DIGITOS] = /* "199" */ /* "99" */  "983456123456123456123456123456123123";
 char c[MAX_DIGITOS+1];
 suma (a,b,c);
 printf ("\n  %s +\n  %s=\n\n %s\n ",a,b,c);
 return 0;
}


La verdad que viendo el código de eferion el mio es como pobre, demasiado cortito.

Y sí, ya, sé debía usar memoria dinámica pero sólo quería algo rapidito para vangodp, ya si procede lo mejoro con las observaciones que aporten. E insisto, es un código modestito, sólo pretendía sumar un par de números grandes.

.....Bueno, está bien, lo mejoro. ¿Cómo?, pues lo de la memoria dinámica lo dejaré otra ocasión, ahora se me apetece otra cosa .......¿y si intentamos que los número grandes puedan estar en cualquier base de 2 a 36?. Es decir poder sumar números grandes en decimal o binario o octal o hexadecimal o ... y así sumar números grandes que estén entre las ya mencionadas bases de 2 a 36, los dos números en la misma base, claro...... otra cosa a mejorar. :)

De antemano aclaro que para bases superiores  a 10 no lo tengo del todo testado, pero creo que sí, que funciona:


Código (cpp) [Seleccionar]
#include <stdio.h>
#include <string.h>

#define MAX_DIGITOS 300 /* o 3000*/
#define DIGITOS   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define BASE  16

void suma (char a[], char b[], char c[]){
 int i,temp,temp_a,temp_b,residuo=0,lon_a,lon_b,dif,digit;
 lon_a = strlen(a);
 lon_b = strlen(b);
 if (lon_a > lon_b){
   dif=lon_a-lon_b;
   for (i=lon_b-1; i >=0;i--)
     b[i+dif]=b[i];
   for (i=0; i < dif;i++)
       b[i]='0';
 }
 else if (lon_b > lon_a){
   dif=lon_b-lon_a;
   for (i=lon_a-1; i >=0;i--)
     a[i+dif]=a[i];
   for (i=0; i < dif;i++)
       a[i]='0';
 }
 for (i=strlen(a)-1; i>=0;i-- ){
   if(a[i]-48>9 )
     temp_a = a[i] -55 ;
   else
     temp_a = a[i] - '0';
   if(b[i]-48>9)
     temp_b = b[i] -55;
   else
     temp_b = b[i] - '0';
   temp = temp_a + temp_b + residuo;
   digit = DIGITOS [temp % BASE];
   if (digit<10)
     c[i+1]=DIGITOS [temp % BASE] + '0';
   else
     c[i+1]=DIGITOS [temp % BASE] ;
   residuo = temp / BASE;
 }
 c[0] = residuo + '0';
 if (c[0]=='0'){
   for (i=0; i < strlen(a);i++ )
     c[i]=c[i+1];
   c[strlen(a)]='\0';
 }
 c[strlen(a)+1]='\0';
}

int main(void){
 /** ¡¡¡ NO OLVIDES CAMBIAR LA BASE DE (2-36) EN #DEFINE¡¡¡ **/
 /** Tienes tres ejemplos: base 16, base 2, base 10 **/
 char a[MAX_DIGITOS] = "A33A15FADBC9"  /*"1001001110111001" */ /*"123456123456123456123456123456123123"*/;
 char b[MAX_DIGITOS] = "FFC593C5BA33A" /*"1001001110111001" */ /* "983456123456123456123456123456123123"*/;
 char c[MAX_DIGITOS+1];
 suma (a,b,c);
 printf ("\n  %s +\n  %s=\n\n %s\n ",a,b,c);
 return 0;
}


Y para que no digan, explico brevemente lo que hace el código:

* Calcula los tamaños de  ambos números y diferencio al de mayor tamaño del de menor.

* Al más pequeño lo relleno con ceros a la izquierda, previo movimiento hacia la derecha de todos sus dígitos para hacer espacio al principio a los ceros, hasta igualar las cifras del mayor.

* Y ya casi está, voy sumando los dígitos de cada uno de los dos números big y si suman más de 10, supuesto están en decimal, pongo el resto como dígito y "me llevo una", eso es el residuo que se sumará, si procede a los dos dígitos siguientes.

* Y para que quede bonito, si el primer caracter del resultado de la suma es cero lo quito moviendo  todos sus dígitos a la izquierda y acortando el tamaño en uno.

La intención es lo que cuenta, como suele decirse. De antemano disculpas si la he pifiado en algo,cosa que espero no haya ocurrido pero ....somos humanos y las prisas no son buenas consejeras. Así que si detectan bugs, porfi avisar.

Y sí, ya sé, el primer código podría usarlo para bases de 2 a 10 sin más que cambiar el "10" que aparece en el mencionado código , por "base" y esta tomar valores de 2 a 10, pero me apetecía ir más allá de la base en decimal xD.


¡¡¡¡ Saluditos! ..... !!!!



eferion

#17
Cita de: leosansan en 30 Abril 2014, 14:15 PM
Bueno si se trata de sumar números grandes en C, aunque no es necesaria, mejor con una función por si nos da por ampliar a resta, producto, etc y con arrays.

En su momento me planteé hacerlo en C... pero claro, la idea que tenía en mente era usar la codificación binaria en vez de por cadena de caracteres... y meter todas las funciones en C dejó de parecerme buena idea XD

Cita de: leosansan en 30 Abril 2014, 14:15 PM
La verdad que viendo el código de eferion el mio es como pobre, demasiado cortito.

Eso es porque tu, al usar cadenas de caracteres, no tienes que realizar conversiones...

Cita de: leosansan en 30 Abril 2014, 14:15 PM
¿y si intentamos que los número grandes puedan estar en cualquier base de 2 a 36?. Es decir poder sumar números grandes en decimal o binario o octal o hexadecimal o ... y así sumar números grandes que estén entre las ya mencionadas bases de 2 a 36, los dos números en la misma base, claro...

Es en esta parte donde el usar la codificación binaria ofrece una solución más sencilla... claro que antes me he tenido que currar el proceso de convertir base 10 a base 2...

Aclaro que me refiero a combinar diferentes bases en una misma operación.

Cita de: leosansan en 30 Abril 2014, 14:15 PM
La intención es lo que cuenta, como suele decirse. De antemano disculpas si la he pifiado en algo,cosa que espero no haya ocurrido pero ....somos humanos y las prisas no son buenas consejeras. Así que si detectan bugs, porfi avisar.

Pifiarla?? yo creo que cuando se hacen propuestas de estas tampoco es plan de que nadie exija que la solución funcione a la perfección en todos los casos... Yo con mi código hice un par de pruebas... si fuese para un desarrollo real le programaría una tira de pruebas bastante contundente.

Además, si alguien cree que puede hacerlo mejor, en vez de criticar, que exponga su solución... así además aprenderemos los demás.

¿No?

Por cierto, me falta alguien en esta conversación con toques matemáticos... qué ha sido de yoel_alejandro??

leosansan

#18
Cita de: eferion en 30 Abril 2014, 14:52 PM
.......................................................................
Pifiarla?? yo creo que cuando se hacen propuestas de estas tampoco es plan de que nadie exija que la solución funcione a la perfección en todos los casos... Yo con mi código hice un par de pruebas... si fuese para un desarrollo real le programaría una tira de pruebas bastante contundente.

Además, si alguien cree que puede hacerlo mejor, en vez de criticar, que exponga su solución... así además aprenderemos los demás.

¿No?

Por cierto, me falta alguien en esta conversación con toques matemáticos... qué ha sido de yoel_alejandro??


Gracias, muchas gracias eferion por tus palabras de comprensión.

Y es cierto, hace días que yoel_alejandro no aparece por el foro, que no "forro" y la verdad es que se hecha de menos sus aportaciones en C, y especialmente, sus puntos de vista matemáticos Con eso de que es de Venezuela espero sinceramente que no le haya pasado nada y que su ausencia se deba a cuestiones de trabajo que tal como están las cosas le vendría muy bien, como a todos, claro.

¡Un fuerte saludo!.



vangodp

gracias a todos chicos.
No te preocupes por si tu código es mejor o peor que el de un compañero leo. Eso nos sirve para tener una visión sencilla sobre el problema. Me sirve mucho igual que las propuestas mas avanzadas ya que soy iniciante. Como mínimo todos aprenderemos algo aquí o por lo menos cambiaremos ideas que nos haga mejorar. ;)
Aquí no es una universidad ni es un colegio de primaria, estamos encerrados todos en un mismo lugar, pero los niños de hoy serán los genios del mañana.
Si veo un código sencillo pues quizás abra ambos y vea lo que no veo en uno solo. ;)

¡¡Soys todos geniales!! Aquí nada se os resiste es fantástico.  ;D