2016-01-25 14 views
11

Esiste un'alternativa per l'utilizzo di BigInteger in java?Alternativa Java BigInteger

quando si esegue un'operazione su BigInteger è risultato sempre con nuovi BigInteger creato. Esiste un'implementazione alternativa in cui il risultato di qualche operazione tra due grandi numeri interi è memorizzato in uno di essi?

Per esempio in Java quando si esegue la moltiplicazione di due grandi numeri interi: a * b un nuovo BigInteger è stato creato per ospitare il risultato. Voglio memorizzare il risultato in a.

voglio che questo, al fine di aumentare le prestazioni in alcuni dei casi di mio algoritmo

+8

Stai sbagliando. Se si desidera aumentare le prestazioni, non utilizzare 'BigInteger' in primo luogo. Qual è esattamente il collo di bottiglia delle prestazioni che vuoi risolvere? – Tunaki

+0

Una risposta tecnica sarebbe scrivere la propria implementazione, ma quello che @Tunaki ha detto è probabilmente meglio. Se stai usando 'BigInteger' in modo così intenso da influenzare le prestazioni, dovresti probabilmente usare qualcos'altro. Se devi usare 'BigInteger', allora accetti il ​​colpo di performance che ne deriva. – Gorbles

+0

In altre parole, stai cercando una sorta di "ModifyableBigInteger"? –

risposta

7

ci sono mutabili "versioni" di BigInteger là fuori (per esempio: https://github.com/bwakell/Huldra) oppure si può rotolare il proprio. L'uso di un oggetto mutabile può ridurre la pressione sul GC. Dovresti davvero confrontare la tua applicazione per vedere se ne vale la pena.

+1

In realtà, Java ha anche una classe MutableBigInteger, ma è usata solo internamente. –

+0

Interessante - usato anche da BigInteger –

13

dubito che le prestazioni del vostro algoritmo migliorerà se si potesse in qualche modo fare questo, ma il principio fondamentale è che BigInteger è immutabile. Non è possibile eseguire un'operazione su di essa senza generare una nuova istanza e ci sono buone ragioni per desiderare questo comportamento - vale a dire, se si dispone di più thread che operano su un singolo BigInteger, si può essere certi che questi thread non stanno sovrascrivendo direttamente questo BigInteger *.

Se non si desidera questo comportamento, l'unica opzione è quella di creare una nuova classe, ma tenere a mente che vi sarà ancora a che fare con l'immutabilità della BigInteger s ad qualche strato.

*: Sai, fino a quando non sei riassegnazione variabile ...

+0

"avremo ancora a che fare con l'immutabilità di BigIntegers su alcuni livelli". - oppure, potresti ri-implementare i big interi da zero (yuck). –

+0

@ JanDvorak: Perché reinventare la ruota? : P – Makoto

+0

@Makoto: le ruote vengono reinventate tutto il tempo. In questo caso, molto probabilmente lo farebbe per ottenere la classe BigInt mutevole di cui si ha bisogno. ;-) Il fatto è che può essere fatto senza affrontare la natura immutabile di BigInteger. –

4

Quello che chiediamo è improbabile che sia in qualche modo più performante tranne quando tutto quello che volete fare è aggiungere. La ragione di ciò è che il numero di bit nel risultato di quasi tutte le operazioni matematiche (diverse da quelle sopra menzionate add) è di dimensioni diverse rispetto al numero originale. Sarà quasi sempre dover allocare un nuovo numero di risultati e copiarlo sull'originale in modo che tutto ciò che si sta facendo sia rallentarlo.

Se, tuttavia, tutto ciò che devi fare è aggiungere/sub, questo è fattibile e potrebbe essere un po 'più veloce in quanto non ci sarà alcuna assegnazione del nuovo array per l'aggiunta.

Quasi tutte le altre funzioni potrebbero essere meglio delegate alla classe BigInteger.

class MutableBigInteger { 
    BigInteger n; 

    public MutableBigInteger add (MutableBigInteger n) { 
     this.n = this.n.add(n.n); 
     return this; 
    } 
} 
+0

Questo è vero solo se si sta eseguendo una sola operazione, ma si consideri il prossimo esempio: a * b/c * d e diventa più complicato. Anche questo mi permette di riutilizzare il mio BigInteger per operazioni future. –

+1

Se c'è un riporto nell'aggiunta delle linbe più alte, la matrice deve essere di 1 lato più lungo degli originali. Inoltre, due valori diversi spesso non hanno le stesse dimensioni, quindi spesso deve avvenire una riallocazione, anche in aggiunta o sottrazione. –

+0

I parametri di riferimento di [Huldra] (https://github.com/bwakell/Huldra) sembrano essere in disaccordo con te. Mi chiedo come farebbero quei benchmark contro Java 8 BigInteger –