2012-04-07 13 views
5

Sto implementando un'implementazione più veloce BigInt e non sono sicuro su quanto dovrei andare per fornire l'interoperabilità con la piattaforma sottostante.Quali problemi devo aspettarmi quando uso Reflection per interfacciare con java.math.BigInteger?

Oggi BigInt solo avvolge una BigInteger e il valore bigInteger solo restituisce il valore avvolto:

class BigInt(val bigInteger: BigInteger) ... 

Perché io non sto avvolgendo un tipo Java, avrei dovuto fare qualcosa di simile

final class BigInt private(final val signum: Int, 
          final private[math] val arr: Array[Int]) 
    def bigInteger: java.math.BigInteger = { 
    // Avoid copying of potentially large arrays. 
    val ctor = classOf[java.math.BigInteger] 
       .getDeclaredConstructor(classOf[Array[Int]], classOf[Int]) 
    ctor setAccessible true 
    ctor.newInstance(arr, signum.asInstanceOf[Object]) 
    } 
... 
} 

Ciò può causare problemi o esiste un modo migliore per farlo?

+0

Non so quanto è grande il numero, ma copiare una piccola serie di intro potrebbe essere più veloce rispetto all'utilizzo del riflesso ... – paradigmatic

+0

Sì, certo. Non importa per i piccoli array, ma la dimensione dei numeri è limitata solo dalla RAM. Semplicemente non voglio mangiare memoria quando si spostano dati da una struttura dati immutabile a un'altra. – soc

+0

Il numero di atomi nell'intero universo è comunemente stimato in 10^80. Con solo 9 * 32 bit, è possibile assegnare un indice univoco a ciascuno. Credo fermamente che se hai bisogno di un numero naturale più grande di quello, probabilmente è un bug o un errore di progettazione ... – paradigmatic

risposta

3

In generale, quando ho visto la gente usa i costruttori o metodi privati ​​(o in altro modo non documentati) in questo modo, essi catturano NoSuchMethodException e fornire un'alternativa:

object BigInt { 
    import java.math.BigInteger 

    private val toBigInteger: (Array[Int], Int) => BigInteger = try { 
    val ctor = classOf[BigInteger].getDeclaredConstructor(
     classOf[Array[Int]], classOf[Int] 
    ) 
    ctor.setAccessible(true) 

    (arr, signum) => ctor.newInstance(arr, signum.asInstanceOf[Object]) 
    } catch { case _: NoSuchMethodException => 
    (arr, signum) => 
     val buffer = java.nio.ByteBuffer.allocate(arr.length * 4) 
     buffer.asIntBuffer.put(arr) 
     new BigInteger(signum, buffer.array) 
    } 
} 

final class BigInt(final val signum: Int, final val arr: Array[Int]) { 
    def bigInteger = BigInt.toBigInteger(arr, signum) 
} 

Ho anche spostato il business riflessione fuori per un oggetto complementare per evitare di pagare la maggior parte di esso ogni volta che si chiama bigInteger.

+0

Approccio interessante, grazie! – soc

+0

Non dovrei cercare 'SecurityException' invece di' NoSuchMethodException'? La cosa divertente è che JavaDoc menziona questo costruttore come pubblico, quindi non penso che scomparirà mai. – soc

Problemi correlati