Java:将 BigInteger 除以 3 / Base 3 表示
Posted
技术标签:
【中文标题】Java:将 BigInteger 除以 3 / Base 3 表示【英文标题】:Java: dividing BigInteger by 3 / Base 3 representation 【发布时间】:2020-03-06 06:39:43 【问题描述】:我需要一种将 BigInteger(1000 字节)除以 3 的快速方法。因为移位不起作用,我必须使用 divideAndReminder()。有更好/更快的选择吗?我经常使用这个,所以很可能 jit 会优化它。
public byte[] div3(BigInteger big)
final List<Byte> al = new ArrayList();
final BigInteger three = BigInteger.valueOf(3);
while(!big.equals(BigInteger.Zero))
final BigInteger[] bigg = big.divideAndReminder(three);
al.add(bigg[1].byteValueExact());
big = bigg[0];
return toByteArray(al);
换档可以更快地完成吗?
【问题讨论】:
(可以使用迭代移位和加/减来完成 - 对于单词操作和没有有用除法的机器很有用。我没有看到任何延续到 multi-word/math.BigInteger。(也就是说,Oracle 运行时包含一个用于乘法的private exactDivideBy3()
。))
不确定是否更快,但你试过BigInteger.toString(3)
吗?
(@user85421:FWIW,Oracles toString(radix)
在 Schönhage 基数转换的实现中使用 divideAndRemainder()
-。)
(@greybeard 它也使用了一个可变的BigInteger
(不是public
),所以它至少有一个优势)
【参考方案1】:
无符号除以 3 可以乘以 0xAA...AA+1,右移 n+1,其中 n 是乘数和 n 是 8(或 4)的倍数。
为了最小化成本,对于给定的股息,您需要一个 n 位乘数,其中 n = 股息的长度,四舍五入为 8 的倍数。我猜这就是private exactDivideBy3()
所做的。 [要为给定的股息构建乘数,您可以从 0xAA...AA 开始,作为您需要处理的最大股息,然后右移或移入 1。您可以保留这些表。]
如果您假设 BigInteger 一次运行 64 位,您当然可以将 n 舍入为 64 的倍数。
【讨论】:
【参考方案2】:虽然 1000 字节似乎不能证明走极端是合理的(Schönhage 基数转换),但一种方法是将 BigInteger
分解为易于处理的部分 - 3^20 或 3^40 外观候选,然后转换为3 从那里。
【讨论】:
以上是关于Java:将 BigInteger 除以 3 / Base 3 表示的主要内容,如果未能解决你的问题,请参考以下文章