fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Variables numericas...
 
Avisos
Vaciar todo

Variables numericas grandes

21 Respuestas
7 Usuarios
0 Reactions
245.3 K Visitas
lacabra25
Respuestas: 84
Topic starter
(@lacabra25)
Trusted Member
Registrado: hace 18 años

Bueno, por el asunto y el resumen seguramente ya estareis imaginando de que va este tema, variables para numeros muy grandes, enormes, de un numero de bits que decida el programador en el momento de programar (y si es posible de un numero de bits que se decida en ejecucion mejor).

Ya tengo conocimientos de programacion en C, y he echo algunos programillas que de momento no han sido gran cosa, he usado la libreria SDL y como anotacion personal me encanta la informatica y cada vez me gustaria programar teniendo mas control sobre lo que programo (a ver si algun dia me animo y me paso por la seccion de ensamblador de este foro para aprender un poco).

Lo que me gustaria saber hacer en C, entre otras cosas, es poder manejar numeros mas grandes de lo que me permite un long o un unsigne long, ¿alguien sabe como o almenos por donde podria empezar a afrontar esta cuestion de variables de numeros grandes?, se que hay multitud de librerias en la red, para esto, para lo otro...; pero me gustaria (igual que hay quien se pone ha hacer librerias ya sea en ensamblador o en C o c++) hacerlo mediante C sin necesidad de usar librerias, se que ahorran trabajo pero es por curiosidad y por saber como hacerlo (y que siempre viene bien saber contra más mejor, y si todos usamos librerias siempre a ver quien se pone a hacerlas despues, jejeje), dejando bromas aparte quisiera saber como manejar numeros muy grandes usando solo C, programandolo manualmente sin complementos ni librerias.

Gracias de antemano a todos por la ayuda que podais brindar y por el tiempo de leeros este tema.

P.D.: en principio no tengo un uso ahora mismo para este tema de numeros muy grandes mas que el de aprender, aunque lo mismo despues si consigo llevar a cabo esta idea de los numeros grandes puede que me anime a aplicarlo en un programa con alguna utilidad y no solo por probar, he leido algunos articulos sobre el algoritmo RSA por lo que podria ser una buena forma de poner en practica el uso de numeros grandes.

Responder
20 respuestas
ranganok
Respuestas: 3875
(@ranganok)
Ardero
Registrado: hace 19 años

Si vas a usar punteros tienes que hacer una reserva de memoria (hace mucho que no las hago pero creo recordar que era con malloc)

En C++ es mucho más fácil e intuitivo ya que puedes crear una clase en la que puedes sobrecargar todos los operadores.

http://www.zator.com/Cpp/E4_9_18.htm

S2

Ranganok Schahzaman

Responder
jorcoval
Respuestas: 418
(@jorcoval)
Reputable Member
Registrado: hace 18 años

punteros lo pense al principio intentando definir un puntero pero no especificandole como tamaño el tamaño de un tipo de dato existente, sino una cantidad como 100 pero si no recuerdo mal me daba error al compilar por algo de poner asi el tamaño del dato al que tenia que apuntar el puntero, ¿se te ocurre alguna forma de definir un puntero que apunte a un dato de x bits de forma que se puedan usar esos x bits todos juntos, como de la misma forma que se usa si fuera un puntero a un int o un long?

Gracias por la sugerencia del array.
Como dice Ranganok, te da error porque no estás reservando memoria. En tiempo de compilación accedes a memoria sin reservar, que puede contener cualquier cosa, y por eso te da error.

Lo que tendrías que hacer es utilizar la función malloc, y definir el tamaño de memoria que quieres reservar.
Por ejemplo, para reservar el tamaño equivalente a 100 integers:
malloc(100*sizeof(int));
Y apuntar con un puntero:
int *p=(int*)malloc(100*sizeof(int));
Es un código muy claro, creo, es solo un casting y la reserva de memoria.

El problema es que de esta forma tienes, ni más ni menos, que un array de 100 enteros. La ventaja evidente es que puedes definir el tamaño en tiempo de ejecución, aunque debes controlar bien el acceso al mismo.
Para acceder a todo como una única variable solo se me ocurre en este momento que crees una función de acceso.
Recuerda además liberar la memoria (free) al acabar

Responder
urriellu
Respuestas: 61
(@urriellu)
Trusted Member
Registrado: hace 18 años

Gracias por las librerias (que segun escriba esto me paso a verlas con detenimiento).¿Ademas no sabras como los que han echo las librerias han echo para hacerlo (a ser posible en C) o de algun articulo que lo explique con algun ejemplo en C o C++?

En lenguajes no-OOP (orientados a objetos) como C no te sabría decir, pero en lenguajes OO lo que se hace es tener un array dinámico (un array que pueda variar su tamaño) y se trabaja sobre sus índices individuales. Por un lado tienes que implementar el array dinámico, y por otra tienes que implementar cada una de las operaciones aritméticas básicas (suma, resta, multiplicación, división, potencias, raíces y logaritmos).

El gran problema son estas operaciones. Intuitivamente pensamos en que para sumar dos valores tomando "trozos del número" (los índices del array donde almacenas su valor) podemos ir sumando a uno de ellos cada índice del otro, y si el valor se desborda entonces aumentamos una unidad el índice posterior. Para restar podría hacerse lo mismo. Luego es "evidente" que multiplicar es sumar múltiples veces, las divisiones restar multiples veces, y las raíces y los algoritmos dividir múltiples veces.

No obstante, esto no es tan símple. Por un lado, estos métodos tan simples de ir sumando, multiplicando... consecutivamente, sólo sirve para números enteros (y las divisiones y logaritmos son operaciones "enteras", osea que el resultado no es exacto, siempre hay un resto), y por otro, es MUY MUY MUY MUY MUY ineficiente, no te puedes imaginar lo tremendamente ineficiente que es.

Hace unos meses yo mismo implementé una clase en C# para poder trabajar con variables enteras de precisión arbitraria (necesitaba que hiciese determinadas cosas que ninguna otra librería soportaba, así que tuve que reescribirla, aunque lo hice más que nada por entretenerme), las operaciones aritméticas las implementé de la forma simple de la que hablé en el tercer párrafo, me llevó unas cuantas horas de trabajo y varios miles de líneas de código (y eso que con C# no tengo que preocuparme de varias cosas que en C o C++ tendrías que fijarte y perder el tiempo con ellas), hice unas pruebas y estimé que el tiempo necesario para dividir dos números que caben en una línea sería de aproximadamente 29 días (core2duo 3ghz con uno de los nucleos al 100%). Me fui a probar otras librerías ya implementadas y esas operaciones las hacía casi instantáneamente.

¿Por qué? Porque hay un montón de teoría y algoritmos matemáticos para poder trabajar con "trozos de números", seguramente tendrás que leer durante horas y horas y quizás leer varios libros para hacer cada una de estas operaciones. No son nada fáciles. Y luego implementarla, otro buen rato.

Como dice Ranganok, lo mejor es usar un lenguaje orientado a objetos y sobrecargar todos los operadores, y que la redimensión del array dinámico donde almacenas los valores sea transparente para el usuario. De esta forma se pueden instanciar objetos derivados de tu clase para números de precisión arbitraria y trabajar con ellos exactamente igual que lo harías con una variable "normal", sin preocuparte de nada más (una vez que la clase esté hecha, claro)

Puedes desensamblar las librerías de .NET (con Reflector) y ver cómo está implementada la clase/variable Decimal (bueno, realmente es un struct, no una clase, pero da igual), sólo para que te hagas una idea porque las operaciones aritméticas no están implementadas en esa librerías (las implementa el CLR internamente, en código nativo). System.Decimal está en la librería mscorlib.

Responder
lacabra25
Respuestas: 84
Topic starter
(@lacabra25)
Trusted Member
Registrado: hace 18 años

jorcoval, probe el codigo que posteastes, pero da un pequeño error.
#include <stdio>

main(){
long *p=(long*)malloc(100*sizeof(long));
long a;
*p= 2149999999;
a= 2139999999;
getch();
return 0;
}

Cambie lo del int por long, que creo que deberia de ser lo mismo pero cogiendo unos cuantos bits mas, y en la prueba para comparar use tambien una variable long pero resulta que el puntero y la variable deben de ser del mismo tamaño pues asignando a ambos el numero 2139999999 no da ningun error, pero intentando que el puntero guarde el numero 2149999999 da error, y segun el codigo se supone que el puntero tiene reservados bits suficientes para guardar un numero 100 veces mas grande que un long, y que se deberia poder asignarle al menos 213999999900 al puntero.

No se cual puede ser la causa, los errores que da el compilador son:

6 C:Documents and SettingsadminMis documentosnumeros gigantes.c [Warning] this decimal constant is unsigned only in ISO C90

Responder
technik
Respuestas: 287
(@technik)
Reputable Member
Registrado: hace 18 años

eso no es un error, es un aviso, has probado a ejecutar el programa igualmente?

Responder
Página 2 / 5
Compartir: