没有BigInteger的Java中两个字节数组的基本算法

时间:2014-06-03 17:38:26

标签: java arrays

我有两个字节数组表示无符号256位值,我想对它们执行简单的算术运算,如ADD,SUB,DIV,MUL和EXP - 有没有办法在字节数组上直接执行这些操作?目前我将这些字节数组值转换为BigInteger,然后执行计算,但我知道这会让我的性能损失。你会怎样做才能获得最快的结果呢?

例如,这是我当前的add-function:

// Both byte arrays are length 32 and represent unsigned 256-bit values
public void add(byte[] data1, byte[] data2) {

    BigInteger value1 = new BigInteger(1, data1);
    BigInteger value2 = new BigInteger(1, data2);
    BigInteger result = value1.add(value2);

    byte[] bytes = result.toByteArray();
    ByteBuffer buffer = ByteBuffer.allocate(32);

    System.arraycopy(bytes, 0, buffer.array(), 32 - bytes.length, bytes.length);
    this.buffer = buffer.array();
}

2 个答案:

答案 0 :(得分:3)

我认为直接使用byte[]而不是使用BigInteger会带来很多好处,但为了满足您的好奇心,这里有一个如何添加大小为{{{ 1}}:

32

请注意,可以使用其中一个输入数组作为结果的目标。但是,如果这种重用对性能产生负面影响,请不要感到惊讶。在今天的系统上,对“如何加速”没有简单的答案......

答案 1 :(得分:1)

对于作为大的无符号数处理,byte []不是理想的解决方案,例如考虑添加其中两个数字,你必须遍历两个数组,添加每个字节(和来自前一个字节的进位),然后将结果字节存储回某处。

BigInteger以适合其提供的操作的方式在内部表示值,因此其操作很可能至少与使用byte []一样好。性能方面的一个小缺点可能是BigInteger是不可变的。

性能方面,由4个长成员组成的简单,可变的持有者对象可能会做得最好:

My256BitNumber {
    long l0;
    long l1;
    long l2;
    long l3;

    public void add(My256BitNumber arg) {
        //...
    }
}

这将允许您绕过对象创建的开销(由于可变),以及任何潜在的数组访问开销(如数组索引边界检查)。

但是考虑到没有任何操作是琐碎的来实现,只需使用BigInteger。它结合了合理的性能和合理的使用简便性,最重要的是 - 它是经过测试的工作解决方案。

如果滚动您自己的实现是值得的,取决于您的用例。考虑到你问如果一个人可以获得比BigInteger更好的性能,答案是,是的,你可以 - 但代价复杂性需要付出高昂代价。