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 表示的主要内容,如果未能解决你的问题,请参考以下文章

如何使用弹簧数据将 BigInteger 转换为 Objectid

JAVA中怎么把int型数据转为BigInteger型数据

BigInteger详解

常见对象BigInteger详解

java之BigInteger类

如何从 Java 中的 BigInteger 获取无符号字节数组?