2011-11-19 12 views
29

Ovviamente, Java non supporta i tipi di numeri non firmati in modo nativo, and that's not going to change soon (commenti che iniziano nel 2002). Tuttavia, quando si lavora con database, come MySQL, possono tornare utili ogni tanto. Ci sono molte domande su come simulare numeri senza segno. Per esempio:Esiste una libreria Java per i wrapper di tipo di numero senza segno?

Tutti loro superficialmente descrivono come potrebbe essere fatto. Ma esiste una libreria in corso e implementando wrapper adatti per UByte, UShort, UInteger, ULong? Preferibilmente, questi involucri dovrebbero estendere java.lang.Number e fornire un'API aritmetica simile a quella di java.math.BigInteger.

Come si può vedere in this document, ci sono molte cose da pensare e molte cose che possono andare storte (ad esempio come cambiare bit per bit, come moltiplicare, ecc.), Quindi non voglio farlo da solo. Inoltre, non voglio utilizzare solo il tipo immediatamente successivo (ad esempio Short anziché Byte, ecc.). Voglio la nozione di un numero 8-bit, 16-bit, 32-bit, 64-bit conservato, per la migliore interazione con i database, per esempio.

UPDATE:

Prima di rispondere! Considera che conosco tutti i metodi alternativi, ma mi piacerebbe davvero avere esattamente quei 4 tipi con esattamente le proprietà sopra. E forse qualcuno lo ha già fatto, ecco perché lo chiedo. Non c'è bisogno di ricordarmi i metodi alternativi.

+4

Tutti gli avvertimenti di bit fudging per giocare senza segno in terra firmata, non avendo "numeri che funzionassero come numeri" in genere sarebbero sufficienti per allontanarmi. Ci sono alcune aree in cui Java è mancato, questo è uno di questi. –

+0

@pst: mi sento lo stesso. Nella maggior parte dei casi anch'io sono distolto. Ma in questo caso, una tale biblioteca sarebbe davvero un piacere. –

+1

Qualche tempo fa ho incontrato la libreria [javolution] (http://javolution.org/target/site/apidocs/javolution/io/Struct.html) con la classe Struct contenente l'implementazione di Uints 8, 16, 32 bit. – 87element

risposta

26

Quando ho bisogno di questa funzionalità all'interno di jOOQ, non ho trovato nulla di simile, così ho arrotolato la mia libreria Open Source che io chiamo jOOU (U per Unsigned):

http://github.com/jOOQ/jOOU

I capire che alcuni possono pensare questo è eccessivo, ma mi piacerebbe molto avere proprio quelle involucri che avvolgono cosa altre lingue chiamano ubyte, ushort, uint, ulong. Spero che con Valhalla questi wrapper possano essere trasformati in tipi di valore.

Naturalmente, contributi per l'aritmetica/bit a bit implementazioni di funzionamento sono i benvenuti!

2

La soluzione che viene utilizzato in commons primitive per una serie di unsignedInt a passare attorno a un lungo considerare questo come un int non firmato. Si può leggere di più qui:

http://commons.apache.org/primitives/apidocs/org/apache/commons/collections/primitives/ArrayUnsignedIntList.html

+0

Grazie, sono a conoscenza di tutte quelle soluzioni parziali. Molte biblioteche hanno adottato 1-2 passaggi verso tipi di numeri non firmati. Ma sto davvero cercando una libreria che faccia esattamente quello che ho descritto nella domanda, una che va fino in fondo, inclusa l'aritmetica ... –

19

ci sono alcune ragioni per cui nessuno ha creato questi wrapper nel modo desiderato.

  • Rappresentazione
  • Garbage collector sovraccarico
  • senza autoboxing/spacchettamento
  • interfaccia cattivo/inutile.
  • facile modi per affrontare esiste

I primi quattro punti sono dimostrate da un piccolo esempio C:

unsigned int x=42, y, m=5, t=18; 
y = x * m + t; 

Questo sarebbe tradotto in:

UInteger m = new UInteger(5); 
UInteger t = new UInteger(18); 
UInteger x = new UInteger(42); 

UInteger y = x.multiplyBy(m); 
y = y.add(t); 

Diversi avvolgitore gli oggetti devono essere creati, multiplyBy e add genereranno un po 'di più. Questo metterà un po 'di peso sul garbage collector se molti calcoli vengono fatti in questo modo.Il wrapping e lo unwrapping mangeranno anche le tue CPU per niente.

Anche la semplice aritmetica è una PITA da scrivere o leggere.

per gli stessi motivi nessuno fa aritmetica utilizzando i tipi di wrapper firmati.

tutto questo è inutile se fate i calcoli utilizzando il tipo firmato prossima grande e tagliare la parte superiore in questo modo:

long x=42, y, m=5, t=18 
y = (x*m + t) & 0xFFFFFFFF; 

Trasferimento tra Java e una banca dati può essere fatto anche con il prossimo più grande tipo firmato E poiché JDBC non creerà questi tipi di wrapper non firmati, sarà necessario farlo da solo solo per trasformare i dati nei wrapper senza segno da quel momento in poi.

Ho fatto qualche CPU di elaborazione dati per me e gestito protocolli binari. In queste occasioni, desideravo anche avere dei tipi di dati non firmati. Ma emularli in Java con i tipi di wrapper sarebbe stato più problematico che affrontare il problema direttamente in ogni singola occasione.

+2

Sono d'accordo, diventa solo "brutto" quando il protocollo binario usa numeri interi a 64 bit senza segno. Ciao BigInteger :( – Voo

+0

Hai dei buoni punti lì, d'altra parte, a volte hai * bisogno di * 'BigInteger' e/o' BigDecimal'. Quindi non hai scelta ma usa quella verbosa API e per gli stessi motivi , se * hai * bisogno di UInteger, perché non usarlo se fosse disponibile? E se sei dentro per la velocità, allora puoi ancora fare i calcoli tu stesso ... Attualmente sto valutando se voglio usa tali wrapper per http://www.jooq.org, o se c'è un altro modo ... Nel mio caso, la velocità non è probabilmente un problema –

+0

@LukasEder sei consapevole che puoi ancora fare l'aritmetica usando il wrapper BigInteger (per 64 bit senza segno) e il valore successivo più grande per tutto il resto e basta dire il DB per memorizzare correttamente i valori? Sono abbastanza sicuro di poterlo fare effettivamente per alcuni DB almeno. – Voo

1

Un'altra libreria da considerare è la di Google Guava. Supporta i seguenti tipi senza segno:

essi estendono Numero e realizzare operazioni aritmetiche.

+0

Per qualche ragione, Guava non ha i tipi 'ushort' e' ubyte'. Nello specifico 'ubyte' è il più utile. Sai perché? –

+0

C'è un problema sollevato per 'short': https://code.google.com/p/guava-libraries/issues/detail?id=670, per' byte' c'è 'UnsignedBytes' – Andrejs

+0

Sì, ma solo' UnsignedBytes' fornisce metodi statici per la manipolazione di 'byte' ... –

2
// Java 8 
    int vInt = Integer.parseUnsignedInt("4294967295"); 
    System.out.println(vInt); // -1 
    String sInt = Integer.toUnsignedString(vInt); 
    System.out.println(sInt); // 4294967295 

    long vLong = Long.parseUnsignedLong("18446744073709551615"); 
    System.out.println(vLong); // -1 
    String sLong = Long.toUnsignedString(vLong); 
    System.out.println(sLong); // 18446744073709551615 

    // Guava 18.0 
    int vIntGu = UnsignedInts.parseUnsignedInt(UnsignedInteger.MAX_VALUE.toString()); 
    System.out.println(vIntGu); // -1 
    String sIntGu = UnsignedInts.toString(vIntGu); 
    System.out.println(sIntGu); // 4294967295 

    long vLongGu = UnsignedLongs.parseUnsignedLong("18446744073709551615"); 
    System.out.println(vLongGu); // -1 
    String sLongGu = UnsignedLongs.toString(vLongGu); 
    System.out.println(sLongGu); // 18446744073709551615 
Problemi correlati