Enteros de mayor precisión en Java

written by uve 17 June 2010

Ahora mismo estoy desarrollando una práctica en la que necesito generar números de 128 bits y escribirlos en un fichero en formato decimal, formato hexadecimal y formato binario.

Empecé jugueteando con C++, y mi sorpresa fue que un long long int utiliza 64 bits bajo una arquitectura de 64 bits. Como el estándar de C/C++ no especifica el tamaño de los tipos de datos esperaba que la últimas versiones del compilador (g++ para ser concretos) utilizasen mayor precisión. Tras esto descarté C++. Existen librerías, como GMP, que nos permiten trabajar con datos de mayor precisión, pero no dispongo de tiempo para investigar.

Lo siguiente en venirme a la cabeza fue Python. La ventaja (y en este caso desventaja) de usar Python es que Python utiliza precisión arbitraria. Esto es, que tú asignas a una variable un entero y te puedes despreocupar. Python asigna dinámicamente el tipo de dato int a la variable, pero si esta crece, en lugar de producir un overflow, le asigna el tipo de dato long y continúa con la ejecución. A partir de ahí, el tipo de dato long crece (reserva de memoria automática) en función de la precisión que necesite. Esto me impide limitar los enteros a 128 bits :(

La opción por la que he optado: Java.

Dentro de la librería util de Java existe la clase BigInteger. Aunque realmente también utiliza precisión arbitraria, de forma similar a Python, mete alguna opción  que me resulta interesante y util. Entre ellas, ofrece un constructor que genera números aleatorios probablemente primos de una precisión indicada (justo lo que necesitaba :). Pero lo mejor es que es extremadamente fácil representar el número en distintas bases:

import java.utils.BigInteger;
BigInteger bi = new BigInteger("1023");
// Formato binario
String s = bi.toString(2); // 1111111111
// Formato octal
s = bi.toString(8); // 1777
// Formato decimal
s = bi.toString(); // 1023
// Formato hexadecimal
s = bi.toString(16); // 3ff

Además nos ofrece constructores para obtener el entero desde distintas bases: binaria, octal, ....

bi = new BigInteger("1111111111", 2); // 1023
bi = new BigInteger("1777", 8); // 1023
bi = new BigInteger("1023"); // 1023
bi = new BigInteger("3ff", 16); // 1023

Y para los números primos aleatorios de 128 bits:

BigInteger x = new BigInteger(128, 2, new Random());

Tags

La teoría es cuando crees saber algo, pero no funciona.
La práctica es cuando algo funciona, pero no sabes por qué.
Los programadores combinan la teoría y la práctica:
Nada funciona y no saben por qué.