Java Mutable BigInteger Class

我正在使用BigIntegers进行计算,该计算使用一个调用乘法()约1000亿次的循环,并且BigInteger的新对象创建使其非常慢。我希望有人写过或找到了一个MutableBigInteger类。我在java.math包中找到了MutableBigInteger,但它是私有的,当我将代码复制到一个新类中时,会出现许多错误,其中大部分我不知道如何修复。

像MutableBigInteger这样的Java类存在哪些实现,允许就地修改值?


答案 1

他们有什么特殊的原因,你不能使用反射来获得对类的访问权限吗?

我能够毫无问题地做到这一点,这是代码:

public static void main(String[] args) throws Exception {       
    Constructor<?> constructor = Class.forName("java.math.MutableBigInteger").getDeclaredConstructor(int.class);
    constructor.setAccessible(true);
    Object x = constructor.newInstance(new Integer(17));
    Object y = constructor.newInstance(new Integer(19));
    Constructor<?> constructor2 = Class.forName("java.math.MutableBigInteger").getDeclaredConstructor(x.getClass());
    constructor2.setAccessible(true);
    Object z = constructor.newInstance(new Integer(0));
    Object w = constructor.newInstance(new Integer(0));

    Method m = x.getClass().getDeclaredMethod("multiply", new Class[] { x.getClass(), x.getClass()});
    Method m2 = x.getClass().getDeclaredMethod("mul", new Class[] { int.class, x.getClass()});
    m.setAccessible(true);
    m2.setAccessible(true);

    // Slightly faster than BigInteger
    for (int i = 0; i < 200000; i++) {
        m.invoke(x, y, z);
        w = z;
        z = x;
        x = w;
    }

    // Significantly faster than BigInteger and the above loop
    for (int i = 0; i < 200000; i++) {
        m2.invoke(x, 19, x);
    }

    BigInteger n17 = new BigInteger("17");
    BigInteger n19 = new BigInteger("19");
    BigInteger bigX = n17;

    // Slowest
    for (int i = 0; i < 200000; i++) {
        bigX = bigX.multiply(n19);
    }
}

编辑:我决定再玩一会儿,看起来java.math.MutableBigInteger的行为并不像你期望的那样。

当您乘法时,它的运行方式不同,并且在分配给自身时必须增加内部数组的大小时,它将引发一个不错的异常。我想这是相当预料之中的。相反,我必须交换对象,以便它始终将结果放入不同的可变BigInteger中。经过几千次计算后,反射产生的开销可以忽略不计。MutableBigInteger最终确实领先,并且随着操作数量的增加,性能越来越好。如果您使用带有整数基元的“mul”函数作为要乘以的值,则MutableBigInteger的运行速度几乎是使用BigInteger的10倍。我想这真的归结为你需要乘以什么值。无论哪种方式,如果您使用可变BigInteger的反射运行此计算“1000亿次”,它将比BigInteger运行得更快,因为内存分配将“更少”,并且它将缓存反射操作,从而消除反射的开销。


答案 2

JScience有一个名为LageInteger的类,这也是不可变的,但他们声称与BigInteger相比,它的性能显着提高。

http://jscience.org/

APFloat的Apint可能也值得一试。http://www.apfloat.org/apfloat_java/


推荐