【问题标题】:Java: dividing BigInteger by 3 / Base 3 representationJava:将 BigInteger 除以 3 / Base 3 表示
【发布时间】: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),所以它至少有一个优势)

标签: java algorithm math biginteger integer-division


【解决方案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 从那里。

    【讨论】:

      猜你喜欢
      • 2016-12-15
      • 1970-01-01
      • 2016-09-11
      • 2013-07-01
      • 2020-02-28
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 2012-07-01
      相关资源
      最近更新 更多