2009-04-20 7 views
10

Estoy buscando un tipo de datos con una capacidad exacta de 0 a 2^64 - 1. Sabemos que Java tal como es no admite el tipo de datos de restricción de caracteres 'sin signo'.¿Cómo implementar un int sin firmar de 64 bits en Java utilizando la clase BigInteger?

Hay clase BigInteger que permite la creación de un mayor número de largo que tipo de datos no puede apoyar. Pero no estoy seguro de cómo la clase BigInteger serviría para mi propósito. La clase BigInteger permite la asignación solo a través de constructores. Veo la siguiente posibilidad pero genera un número aleatorio.

BigInteger(int numBits, Random rnd) 
Constructs a randomly generated BigInteger, uniformly distributed over the range 0 to (2^numBits - 1), inclusive. 

no puedo ver cualquier tipo setValue (x) de la API que me dejaran elegir mi propio valor a esta BigInteger. ¿Cómo implementar esto usando la clase BigInteger o hay alguna otra forma de hacerlo? Por favor, publique el código de muestra.

PD: La pregunta publicada por alguien here no tiene detalles de implementación.

+1

¿Puedes aclarar exactamente por qué necesitas el tipo de datos y qué intentas hacer con él? Puede haber formas de simplificar el problema ... – Alnitak

+0

C++ admite dicho tipo de datos.Estoy interactuando con C++ y pensé que sería mejor tener un tipo de datos similar en Java también en lugar de tener que manipular los datos y convertirlos en C++. –

Respuesta

1

BigInteger s son inmutables, tal como lo has encontrado. Es posible que desee considerar la creación de subclases de BigInteger, y escribir su propio constructor que valide la entrada, y que emita un BigInteger positivo en el rango relevante.

Para mantener el requisito de que los números solo usan 64 bits, es posible que tenga que sobrecargar las diversas operaciones también, por lo que limitan el resultado y devuelven una instancia de su nueva clase en lugar de un nuevo BigInteger.

Esto es probablemente un poco de trabajo, pero aún así debería ser mucho mejor que hacerlo todo desde cero.

1

Puede crear un BigInteger de un largo con BigInteger.valueOf (l), donde l es un largo.

Pero si se quiere trabajar con exactamente 64 bits, que haría uso de sólo el tiempo.

3

Por qué no escribir su propio envoltorio y el uso debajo de una larga firmado. Si el usuario desea obtener el valor sin firmar como BigInteger, pruebe el signo y agregue 2^64 al BigInteger.

2

es posible que desee crear una clase UInt64, que encapsulan una BigInteger; también puede verificar que cada operación (agregar, mul, etc.) devuelva un BigInteger de 64 bits sin signo; simulando el desbordamiento tal vez complicado

class UInt64 { 

    private final BigInteger value; 

    private UInt64(BigInteger aValue) { 
     // method to enforce your class invariant: 0...2**64-1 
     checkInvariantOf(aValue); 
     value = aValue; 
    } 

    public static UInt64 of(String value) { 
     return new UInt64(new BigInteger(value)); 
    } 

    public UInt64 add(UInt64 v) { 
     return new UInt64(value.add(v.value)); 
    } 

    .... 
} 
7

A menudo puede utilizar los tipos de datos numéricos con signo de Java como si fueran sin firmar.

Consulte este old answer sobre firmado vs no firmado en Java.

1

puede almacenar valores 0 a 2^64-1 en un valor de largo.

Muchas operaciones funcionan como se esperaba, sin embargo, la mayoría de las API y algunas de las operaciones solo funcionan, ya que asumen operaciones firmadas, sin embargo, existen soluciones provisionales.

Usando BigInteger puede ser más fácil de conseguir su cabeza alrededor sin embargo. ;)

+0

largo admite -2^63 a (2^63) -1 ya que el primer bit es el bit de signo. Quiero unsigned long, que entonces estaría en un rango de 0 a (2^64) -1. No es 2^(64-1) lo que quiero. Es (2^64) -1. –

+2

Creo que la distinción depende de usted. Si usa +, -, ^, &, |, <<, > >>, ~ encontrará que el resultado es indistinguible. Si llama Long.toHexString (long), no imprimirá un número negativo. –

+1

También == y! =;) –

1

En Java SE 8 y posterior, puede usar el tipo de datos largos para representar un largo sin signo de 64 bits, que tiene un valor mínimo de 0 y un valor máximo de 2^64-1.

+1

Sería muy útil agregar un ejemplo de código a esta respuesta, o un enlace a cierta documentación. – CubeJockey

+0

http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html - Observe las nuevas funciones ... 'compareUnsigned' y tal ... Esto también apunta hacia lo que Peter Lawrey estaba diciendo en sus respuestas y comentarios. –

Cuestiones relacionadas