2012-04-07 7 views
5

Wdrażam szybszą implementację BigInt i nie jestem pewien, jak daleko należy się posunąć, aby zapewnić współdziałanie z podstawową platformą.Z jakimi problemami muszę się spodziewać podczas używania Reflection do interfejsu z java.math.BigInteger?

Dziś BigInt tylko owija BigInteger a wartość bigInteger prostu zwraca owinięte wartość:

class BigInt(val bigInteger: BigInteger) ... 

bo nie jestem owijanie typu Java, chciałbym coś zrobić jak

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

Czy może to powodować problemy, czy jest lepszy sposób na zrobienie tego?

+0

Nie wiem, jak duża jest liczba, ale skopiowanie małej tablicy int może być szybsze niż użycie odbicia ... – paradigmatic

+0

Tak, oczywiście. Nie ma znaczenia dla małych tablic, ale rozmiar liczb jest ograniczony tylko przez pamięć RAM. Po prostu nie chcę jeść pamięci podczas przenoszenia danych z niezmiennej struktury danych do innej. – soc

+0

Liczba atomów w całym wszechświecie jest zwykle szacowana na 10^80. Tylko 9 * 32 bitów, możesz przypisać unikalny indeks do każdego z nich. Mocno wierzę, że jeśli potrzebujesz naturalnej liczby większej, to prawdopodobnie błąd lub błąd projektu ... – paradigmatic

Odpowiedz

3

Na ogół, gdy widziałem ludzie używają prywatnych (lub inaczej nieudokumentowane) konstruktorów i metod tak, złapią NoSuchMethodException i stanowić alternatywę:

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

Ja również przeniósł działalność do refleksji off obiekt towarzyszący, aby uniknąć płacenia za większość z nich za każdym razem, gdy dzwonisz pod numer bigInteger.

+0

Interesujące podejście, dzięki! – soc

+0

Czy nie musiałbym zwracać uwagi na 'SecurityException' zamiast' NoSuchMethodException'? Zabawne jest to, że JavaDoc wspomina o tym konstruktorze jako publicznym, więc nie sądzę, że kiedykolwiek zniknie. – soc

Powiązane problemy