Java可变BigInteger类

Java可变BigInteger类,java,performance,precision,biginteger,mutable,Java,Performance,Precision,Biginteger,Mutable,我正在使用BigInteger进行计算,它使用一个循环调用multiply()大约1000亿次,而从BigInteger创建新对象的速度非常慢。我希望有人已经编写或发现了一个可变的BigInteger类。我在java.math包中找到了MutableBigInteger,但它是私有的,当我将代码复制到一个新类中时,会出现许多错误,其中大部分我不知道如何修复 像MutableBigInteger这样的Java类存在哪些允许就地修改值的实现?JScience有一个类调用LargeInteger,该类

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


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

JScience有一个类调用LargeInteger,该类调用也是不可变的,但他们声称与BigInteger相比,该类的性能显著提高


APFloat的Apint可能也值得一看

您不能使用反射来访问类有什么特殊原因吗

我能够做到这一点,没有任何问题,以下是代码:

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);
    }
}
publicstaticvoidmain(字符串[]args)引发异常{
构造函数Constructor=Class.forName(“java.math.MutableBigInteger”).getDeclaredConstructor(int.Class);
constructor.setAccessible(true);
objectx=constructor.newInstance(新整数(17));
objecty=constructor.newInstance(新整数(19));
构造函数constructor2=Class.forName(“java.math.MutableBigInteger”).getDeclaredConstructor(x.getClass());
构造函数2.setAccessible(true);
objectz=constructor.newInstance(新整数(0));
Object w=constructor.newInstance(新整数(0));
方法m=x.getClass().getDeclaredMethod(“乘法”,新类[]{x.getClass(),x.getClass()});
方法m2=x.getClass().getDeclaredMethod(“mul”,新类[]{int.Class,x.getClass()});
m、 setAccessible(true);
m2.可访问设置(真);
//比BigInteger稍快
对于(int i=0;i<200000;i++){
m、 调用(x,y,z);
w=z;
z=x;
x=w;
}
//明显快于BigInteger和上面的循环
对于(int i=0;i<200000;i++){
m2.调用(x,19,x);
}
BigInteger n17=新的BigInteger(“17”);
BigInteger n19=新的BigInteger(“19”);
BigInteger bigX=n17;
//最慢的
对于(int i=0;i<200000;i++){
bigX=bigX.乘法(n19);
}
}
编辑: 我决定再做一点,java.math.MutableBigInteger的行为似乎与您预期的不完全一样


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

我复制了MutableBigInteger,然后注释掉了一些我不需要的方法体,添加了一个

throw new UnsupportedOperationException("...");
调用时

这就是它的样子

在中,您可以看到原始java.math.MutableBigInteger的变化

我还增加了一些方便的方法,

public void init(long val) {};
public MutableBigInteger(long val) {};
// To save previous value before modifying.
public void addAndBackup(MutableBigInteger addend) {}
// To restore previous value after modifying.  
public void restoreBackup() {}
下面是我如何使用它的:

private BigInteger traverseToFactor(BigInteger offset, BigInteger toFactorize, boolean forward) {
    MutableBigInteger mbiOffset = new  MutableBigInteger(offset);
    MutableBigInteger mbiToFactorize = new MutableBigInteger(toFactorize);
    MutableBigInteger blockSize = new MutableBigInteger(list.size);

    if (! MutableBigInteger.ZERO.equals(mbiOffset.remainder(blockSize))) {
        throw new ArithmeticException("Offset not multiple of blockSize");
    }

    LongBigArrayBigList pattern = (LongBigArrayBigList) list.getPattern();

    while (true) {
        MutableBigInteger divisor = new MutableBigInteger(mbiOffset);
        for (long i = 0; i < pattern.size64(); i++) {
            long testOperand = pattern.getLong(i);
            MutableBigInteger.UNSAFE_AUX_VALUE.init(testOperand);
            divisor.addAndBackup(MutableBigInteger.UNSAFE_AUX_VALUE);
            if (MutableBigInteger.ZERO.equals(mbiToFactorize.remainder(divisor))) {
                return divisor.toBigInteger();
            }
            divisor.restoreBackup();
        }

        if (forward) {
            mbiOffset.add(blockSize);
        } else {
            mbiOffset.subtract(blockSize);
        }
        System.out.println(mbiOffset);
    }
}
private BigInteger traverseToFactor(BigInteger偏移量、BigInteger ToFactory、布尔向前){
MutableBigInteger mbiOffset=新的MutableBigInteger(偏移量);
MutableBigInteger MBiToFactoryize=新的MutableBigInteger(ToFactoryize);
MutableBigInteger blockSize=新的MutableBigInteger(list.size);
如果(!MutableBigInteger.ZERO.equals(mbiOffset.Requirement(blockSize))){
抛出新的算术异常(“偏移量不是块大小的倍数”);
}
LongBigArrayBigList模式=(LongBigArrayBigList)list.getPattern();
while(true){
MutableBigInteger除数=新的MutableBigInteger(mbiOffset);
对于(长i=0;i
您是如何确定BigInteger的创建速度慢的?基本体的创建速度快,而且我知道对象创建的开销很大,因此,我认为是创建造成了大部分延迟。这里可以找到部分答案:将类添加到您的
public
版本中,添加到启动类路径或
jre/lib/approved
目录中,以避免此错误/警告。我的jre/lib没有approved目录。制作一个BigInteger类也比我想象的要困难得多。我仍然在为加密的BigInteger性能而挣扎。在分形之前,我用的是Apfloat,比bigdecimal差。我不希望apint会比BigInteger更好。使用Peter Lawrey评论中的jre/lib/annowed可能是使用MutableBigInteger的方法想要使用MutableBigInteger的原因是性能。利用反射波