2009-04-20 9 views
10

Sto cercando un tipo di dati con una capacità esatta da 0 a 2^64 - 1. Sappiamo che Java così com'è non supporta il tipo di dati char "senza segno".Come implementare un int non firmato a 64 bit in Java utilizzando la classe BigInteger?

C'è una classe BigInteger che consente la creazione di numeri più grandi che un tipo di dati lungo non può supportare. Ma non sono sicuro di come la classe BigInteger possa servire al mio scopo. La classe BigInteger consente l'assegnazione solo tramite i costruttori. Vedo la seguente possibilità ma genera un numero casuale.

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

non riesco a vedere alcun setValue (x) tipo di API che sarebbe lascia decidere il mio valore a questo BigInteger. Come implementarlo usando la classe BigInteger o esiste un altro modo per farlo? Per favore pubblica un esempio di codice.

PS: la domanda inviata da qualcuno here non ha dettagli di implementazione.

+1

Puoi chiarire esattamente perché hai bisogno del tipo di dati e di cosa stai cercando di fare? Ci possono essere modi per semplificare il problema ... – Alnitak

+0

C++ supporta tale tipo di dati.Sto interagendo con C++ e ho pensato che sarebbe stato meglio avere un datatype simile anche a Java piuttosto che dover manipolare i dati e convertirli in C++. –

risposta

1

BigInteger s sono immutabili, proprio come hai trovato. Si potrebbe voler esaminare la sottoclasse di BigInteger e scrivere il proprio costruttore che convalida l'input ed emette un BigInteger positivo nell'intervallo pertinente.

Per mantenere il requisito che i numeri utilizzino solo 64 bit, potrebbe essere necessario sovraccaricare anche le varie operazioni, in modo da limitare il risultato e restituire un'istanza della nuova classe anziché un nuovo BigInteger.

Questo è probabilmente un bel po 'di lavoro, ma dovrebbe essere ancora molto meglio di fare tutto da zero.

1

È possibile creare un BigInteger da molto tempo con BigInteger.valueOf (l), dove l è un lungo.

Ma se si vuole lavorare con 64 bit esatti, lo userei solo a lungo.

3

Perché non scrivere il proprio wrapper e utilizzare una firma lunga. Se l'utente desidera recuperare il valore unsigned come BigInteger - prova il segno e aggiungi 2^64 a BigInteger.

2

potresti voler creare una classe UInt64 che incapsuli un BigInteger; puoi anche controllare che ogni operazione (aggiungi, mul, ecc.) restituisca un BigInteger a 64 bit senza segno; simulando l'overflow forse difficile

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

Spesso è possibile utilizzare i tipi di dati numerici firmati di Java come se fossero senza segno.

Vedere questo old answer su firmato e non firmato in Java.

1

È possibile memorizzare valori da 0 a 2^64-1 in un valore lungo.

Molte operazioni funzionano come previsto, tuttavia la maggior parte delle API e alcune delle operazioni funzionano solo in quanto presuppongono operazioni firmate, tuttavia esistono soluzioni alternative.

L'utilizzo di BigInteger potrebbe essere più semplice per avere la testa in ogni caso. ;)

+0

long supporta -2^63 a (2^63) -1 come primo bit è il bit di segno. Voglio unsigned long che dovrebbe andare da 0 a (2^64) -1. Non è 2^(64-1) che voglio. È (2^64) -1. –

+2

Credo che la distinzione dipenda da voi. Se usi +, -, ^, &, |, <<, > >>, ~ troverai che il risultato è indistinguibile. Se si chiama Long.toHexString (long), non verrà stampato un numero negativo. –

+1

== e! =;) –

1

In Java SE 8 e versioni successive, è possibile utilizzare il tipo di dati lunghi per rappresentare una lunghezza di 64 bit senza segno, che ha un valore minimo di 0 e un valore massimo di 2^64-1.

+1

Sarebbe molto utile aggiungere un esempio di codice a questa risposta o un collegamento ad alcuni documenti. – CubeJockey

+0

http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html - Notate le nuove funzioni ... 'compareUnsigned' e così ... Questo suggerisce anche cosa Peter Lawrey stava dicendo nelle sue risposte e commenti. –

Problemi correlati