2009-05-21 19 views

risposta

3
/** 
* A class used to represent multiprecision integers that makes efficient 
* use of allocated space by allowing a number to occupy only part of 
* an array so that the arrays do not have to be reallocated as often. 
* When performing an operation with many iterations the array used to 
* hold a number is only reallocated when necessary and does not have to 
* be the same size as the number it represents. A mutable number allows 
* calculations to occur on the same number without having to create 
* a new number for every step of the calculation as occurs with 
* BigIntegers. 
* 
* @see BigInteger 
* @version 1.12, 12/19/03 
* @author Michael McCloskey 
* @since 1.3 
*/ 

Source.

Direi che MutableBigInteger è utilizzato internamente per calcoli pesanti BigInteger che vengono rallentati da frequenti riallocazioni. Non sono sicuro del motivo per cui non è stato esportato come parte di java.math. Forse un po 'di disgusto per le classi di valore mutabili?

Per chiarire "mutabile":
standard BigInteger ha un valore per tutta la sua durata, data due riferimenti BigInteger "a" & "b", "A + B" sarà sempre produrre una nuova BigInteger con lo stesso valore. Diciamo che il valore è 4.

Con MutableBigInteger, "a + b" potrebbe produrre inizialmente 4, ma restituire 8, 16, 32 o qualsiasi altro numero in un determinato momento nel futuro a causa di un altro codice che modifica i valori (aka. mutating) degli oggetti referenziati da "a" & "b". Di conseguenza, la maggior parte (forse tutti) dei tipi di valore (Character, Short, Long, Integer, BigInteger, BigDecimal, Float, Double, Even String) in Java sono immutabili.

+0

Grazie per la risposta. Forse le domande dovrebbero essere: "Perché non è una classe pubblica?". Penso che una tale classe possa essere molto utile, specialmente per le variabili di loop. –

+0

Ho ampliato la mia risposta un po 'di conseguenza. Fondamentalmente, probabilmente non è mutabile perché anche altri tipi di valore non sono mutabili. È una convenzione, davvero. –

4

Il problema con BigInteger è che è immutabile: in altre parole, una volta che si dispone di un oggetto BigInteger, non è possibile modificare il valore dell'oggetto stesso, è possibile solo sostituirlo con un nuovo oggetto.

Ora questa è normalmente una buona cosa, poiché impedisce l'aliasing e così via (non vuoi che il tuo "2 + 3" da qualche parte si trasformi improvvisamente in "2 + 5" perché un utente di quel "3" da qualche parte altrimenti nel tuo programma lo ha cambiato in un "5"). Tuttavia, internamente BigInteger utilizza una matrice per contenere i componenti di questo valore. Per un numero elevato, questo array può essere abbastanza grande; un BigInteger che rappresenta un bilione potrebbe avere bisogno di un array di, oh, mille elementi, per esempio.

Quindi cosa succede quando voglio aggiungerne uno a questo BigInteger? Bene, creiamo un nuovo BigInteger, che a sua volta creerà un nuovo array interno ad esso di un migliaio di elementi, copia tutti gli elementi del vecchio array interno di BigInteger al nuovo array interno di BigInteger, eccetto l'ultimo, e inserisce una nuova versione dell'ultimo elemento incrementata di uno. (Oppure potrebbe essere necessario aggiornare gli ultimi due.) Se non si ha bisogno del vecchio valore, si libera quel vecchio BigInteger, che libera l'array.

Questo è ovviamente abbastanza inefficiente se sono solo sbarazzarsi dei vecchi valori in ogni caso. Quindi, se hai operazioni come questa, puoi invece usare un MutableBigInteger, che può essere incrementato semplicemente cambiando l'ultimo elemento dell'array interno del MutableBigInteger esistente. Questo è molto più veloce! Tuttavia, distrugge il vecchio valore, che può essere problematico, come ho sottolineato sopra. Se qualcuno ti dà l'int "3", puoi aspettarti che rimanga lo stesso. Se qualcuno ti dà un MutableBigInteger, non aspettarti che sia lo stesso numero più tardi!

+0

Grazie per la risposta. Hai descritto il modo in cui la classe funziona molto bene. Ma ti sei perso una cosa: la classe non è pubblica (dichiarata senza o con il modificatore predefinito). Quindi non è disponibile al di fuori del pacchetto java.math. –

+0

@ c0d3x e Curt, non c'è certamente niente di sbagliato nel creare un flag immutabile per il costruttore in una classe altrimenti immutabile, o viceversa. Questo sicuramente proteggerà il tuo "3". Sono più che un po 'infastidito dal fatto che non ci siano LongLong e simili per le varianti di BigInteger. Sento che questo business immutabile è un maldestro pezzo di pedanteria e viola la legge della sorpresa minima, sia quando lo si usa, sia quando si legge il codice che lo usa. Seriamente, qualcuno di voi ne ha visto una pagina? È solo schifoso. –

+0

Ho visto decine di migliaia di linee di codice quasi senza immutabilità. Si chiama Haskell ed è meraviglioso. :-) Onestamente, rendere la maggior parte dei tuoi dati immutabili semplifica quasi sempre la programmazione. Tuttavia, è spesso vero che, nei sistemi che dipendono fortemente dalla mutabilità in tutto il sistema, il tentativo di introdurre l'immutabilità può diventare imbarazzante. Questo non è davvero un problema con il concetto; è un problema con esso non applicato bene. –

1

MutableBigInteger fa riferimento nella libreria java.math. Se hai installato un JDK, controlla i contenuti di src.zip nella tua directory jdk.

Vedrete BigInteger lo usa:

public BigInteger divide(BigInteger val) { 
    MutableBigInteger q = new MutableBigInteger(), 
         r = new MutableBigInteger(), 
         a = new MutableBigInteger(this.mag), 
         b = new MutableBigInteger(val.mag); 

    a.divide(b, q, r); 
    return new BigInteger(q, this.signum * val.signum); 
} 

MutableBigInteger è un incapsulamento degli algoritmi matematici utilizzati da BigInteger.