2012-04-07 12 views
5

Implemento una implementación más rápida BigInt y no estoy seguro de qué tan lejos debería llegar para proporcionar interoperabilidad con la plataforma subyacente.¿Qué problemas debo esperar al usar Reflection para interactuar con java.math.BigInteger?

Hoy BigInt simplemente se ajusta un BigInteger y el valor bigInteger sólo devuelve el valor envuelta:

class BigInt(val bigInteger: BigInteger) ... 

Porque no estoy envolviendo un tipo Java, que tendría que hacer algo como

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]) 
    } 
... 
} 

¿Esto puede causar problemas o hay una mejor manera de hacerlo?

+0

No sé cuán grande es el número, pero copiar una pequeña serie de entradas podría ser más rápido que usar la reflexión ... – paradigmatic

+0

Sí, claro. No importa para arreglos pequeños, pero el tamaño de los números solo está limitado por la RAM. Simplemente no quiero comer memoria cuando muevo datos de una estructura de datos inmutable a otra. – soc

+0

El número de átomos en todo el universo se estima comúnmente en 10^80. Con solo 9 * 32 bits, puede asignar un índice único a cada uno. Creo firmemente que si necesitas un número natural más grande que eso, probablemente sea un error o un error de diseño ... – paradigmatic

Respuesta

3

En general, cuando he visto la gente usa constructores o métodos privados (o de otra manera sin papeles) de este tipo, que capturan NoSuchMethodException y proporcionan una 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) 
} 

también me he movido el negocio fuera de reflexión un objeto complementario para evitar pagar la mayor parte cada vez que llame al bigInteger.

+0

¡Un enfoque interesante, gracias! – soc

+0

¿No tendría que buscar 'SecurityException' en lugar de' NoSuchMethodException'? Lo divertido es que JavaDoc incluso menciona que este constructor es público, así que no creo que desaparezca. – soc

Cuestiones relacionadas