我有两个字节数组表示无符号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();
}
答案 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更好的性能,答案是,是的,你可以 - 但代价复杂性需要付出高昂代价。