¿Como se trabaja con big integers en C?

Iniciado por soplo, 14 Octubre 2010, 21:11 PM

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

soplo

Pues eso.

¿Como defino en C un tipo bigint o similar que admita números grandes? ¿hay alguna librería? ¿como se hace?
Callar es asentir ¡No te dejes llevar!

Horricreu

#1
Existe un tipo de dato llamado long int o simplemente long (que ocupa 4 bytes) y, cuando es signado va desde el -2147483648 hasta el 2147483647 y cuando no es signado va desde el 0 hasta el 4294967295.

soplo

#2
Hombre claro que los long son mayores que los int pero eso no son big int. Un big int puede tener 200 dígitos.

Estoy trabajando en unos test de primalidad (miller-rabin) y no tengo problema con números muy pequeños pero con números de dos o tres cifras ya no puedo. Lo correcto sería trabajar con números de mínimo veinte cifras osea que el long no vale ni de coña. Intenta calcular 50^100 o 60! o cualquier cosa asi con el tipo long.

Yo creo que hay alguna librería que se incluye y que tiene funciones para eso pero no se donde encontrarla ni nada. Por eso pregunto.

Un saludo
Callar es asentir ¡No te dejes llevar!

Akai

#3
En vez de trabajar con enteros, quizá podrías probar con doubles, (o long doubles). No son tipos puramente de enteros, pero su rango de representación abarca números mayores.

Sin embargo, esto te puede acarrear que algunos de tus números no sean representables por la propia naturaleza del formato en coma flotante y tengas problemas de redondeo.

soplo

Efectivamente tal como dices no es posible utilizar coma flotante y de hecho aún así habría un límite (mayor pero límite) que lo hace inviable. Podría ocurrir que pudieras calcular 50! y no pudieras 51! por ejemplo. La naturaleza de big int es "cualquier tamaño" y lo que si puede pasar es que según la cpu que tengas la operación pueda llevar mas o menos tiempo.

En google veo que algunos códigos hacen un include "bigint.h" y a partir de ahí ya se puede trabajar con ese tipo de números, pero no consigo información de donde obtenerlo.

Un saludo
Callar es asentir ¡No te dejes llevar!

WestOn

Jeje te gusto lo de criptografía :P
¿Probaste este?

Saludos y ya me cuentas como te fue (no puedo probarlo ahora, por eso te lo pregunto).
;)
En mi cabeza existe una barrera espacio-tiempo de 4cm³. ¿Alguien sabe como eliminarla?.
                                                                                                                                                                                                                            

soplo

#6
Eso si es lo que busco o al menos lo parece (a falta de pruebas)
;D

He mirado eso de gmp.h y creo que la cosa pasa por instalar los paquetes libgmp-ocaml y libgmp3c2 (en debian).

Esto si parece ser lo que buscaba.

Si que me gustó la criptografía. Es una ciencia aparte y un nuevo reto je je je. Igual me ha pasado con Gambas como lenguaje de programación para sustituir a VB y en entornos linux. Disfruto con ello.

Muchas gracias
;D

Lh: No hagas doble post, utiliza el botón modificar.

Ya lo he solucionado. Ahora que lo veo no es tna dificil pero ha habido un rato que no enteraba por donde me venían las cosas.

Primero para instalarlo hay que instalar los paquetes libgmp3c2 y libgmp3-devel.

Una vez instalado hay que conocer las funciones que incluye para trabajo con bignum. La documentación de esas funciones está aquí

http://gmplib.org/manual/index.html#Top

Y mas concretamente las funciones correspondientes están aquí
http://gmplib.org/manual/Function-Classes.html#Function-Classes

Y ahora pongo un ejemplo de crear un número grande y hacer una suma con él. Luego se muestra en pantalla.

# include <gmp.h>

int main(void)
{
   mpz_t x,y,z;

   mpz_init(x);
   mpz_init(y);
   mpz_init(z);
   mpz_set_str(x,"987654321987654321987654327",10);
   mpz_set_str(y,"1",10);
   mpz_add(z,x,y);
   mpz_out_str(stdout,10,z);
   return(0);
}


Primero inicializo x, y y z. Luego asigno a x un valor que especifico que está en base 10. Asigno a y el valor 1 y especifico que está en base 10. Luego sumo x e y y dejo el resultado en z que hasta ese momento valía cero. Por último saco por stdout el valor de z.

Muchas gracias
;D

[editado]
Olvidé decir que para compilarlo hay que incluir obligatoriamente la librería gmp o no funcionará.
Es decir pra compilar la anterior aplicación y que funcione habrá que hacerlo así
gcc prueba.c -lgmp -o prueba

[/editado]
Callar es asentir ¡No te dejes llevar!

Foxy Rider

Aclaración :

@E.P.I:  Estás describiendo el int ... un long en condiciones normales es de 64 bits, no 32  ..
2^32 = 4,294,967,296 (si no, le sacás un bit para el signo)

Saludos.

Littlehorse

Lo que expuso Horricreu es correcto ya que no se refiere al máximo de posibilidades si no al rango comprendido.

Cita de: Horricreu en 14 Octubre 2010, 22:20 PM
y cuando no es signado va desde el 0 hasta el 4294967295.

es perfectamente correcto.
En cuanto a los bytes, el requerimiento mínimo de un long es de 4 bytes, y de ahí para arriba puede variar dependiendo la plataforma y la arquitectura en la que estemos trabajando.
long long en todo caso si requiere como mínimo 64bits, pero esa es otra historia ya que esto no se ha mencionado aquí.

Saludos
An expert is a man who has made all the mistakes which can be made, in a very narrow field.

Foxy Rider

Cierto, fail mío, me confundí con el tema de la arquitectura (en 64 bits automáticamente es 8 bytes), cierto que en 32 es 4 ...

Saludos.